In this project we will create an application that can change the theme of a paragraph real-time using elements on the front-end. We will also create a switch that can enable and disable the ability to change the theme of the paragraph. In the process of creating this project, we will cover how to use this, bind, state, and props.
forkandclonethis repository.cdinto the project directory.- Run
npm install. - Run
npm startafternpm installhas finished.
In this step, we will create the initial state for src/App.js. On this state object, we will keep track of the initial theme values and if the theme is allowed to be edited.
- Open
src/App.js. - Create a
constructormethod where it says// constructor:- This method should call
super(). - This method should create an initial state object with the following properties:
- fontColor: 'black',
- fontSize: 12,
- fontFamily: 'monospace',
- allowEdit: 'true'
- This method should call
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
}
// updateColor
// updateSize
// updateFamily
// updateEditStatus
render() {
return (
<div>
<div className="headerBar">
{ /* Render EditToggle */ }
{ /* Render ColorChanger */ }
{ /* Render SizeChanger */ }
{ /* Render FamilyChanger */ }
</div>
<div className="textArea">
{ /* Render TextContainer */ }
</div>
</div>
)
}
}
export default App;In this step, we will create class methods in src/App.js to update fontColor, fontSize, fontFamily, and allowEdit on state.
- Open
src/App.js. - Create an
updateColormethod that takes a parameter calledvalwhere it says// updateColor:- Use
setStateto updatefontColortoval.
- Use
- Create an
updateSizemethod that takes a parameter calledvalwhere it says// updateSize:- Use
setStateto updatefontSizetoval.
- Use
- Create an
updateFamilymethod that takes a parameter calledvalwhere it says// updateFamily:- Use
setStateto updatefontFamilytoval.
- Use
- Create an
updateEditStatusmethod that takes a parameter calledvalwhere it says// updateEditStatus:- Use
setStateto updateallowEdittoval.
- Use
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
}
updateColor(val) {
this.setState({ fontColor: val });
}
updateSize(val) {
this.setState({ fontSize: val });
}
updateFamily(val) {
this.setState({ fontFamily: val });
}
updateEditStatus(val) {
this.setState({ allowEdit: val });
}
render() {
return (
<div>
<div className="headerBar">
{ /* Render EditToggle */ }
{ /* Render ColorChanger */ }
{ /* Render SizeChanger */ }
{ /* Render FamilyChanger */ }
</div>
<div className="textArea">
{ /* Render TextContainer */ }
</div>
</div>
)
}
}
export default App;In this step, we will bind this to our methods in the constructor method in App.js. We'll need to bind this on the updateEditStatus, updateColor, updateSize, and updateFamily methods.
- Open
src/App.js. - Bind
thisto theupdateColor,updateSize,updateFamily, andupdateEditStatusmethods at the bottom of theconstructormethod.
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
this.updateColor = this.updateColor.bind( this );
this.updateSize = this.updateSize.bind( this );
this.updateFamily = this.updateFamily.bind( this );
this.updateEditStatus = this.updateEditStatus.bind( this );
}
updateColor(val) {
this.setState({ fontColor: val });
}
updateSize(val) {
this.setState({ fontSize: val });
}
updateFamily(val) {
this.setState({ fontFamily: val });
}
updateEditStatus(val) {
this.setState({ allowEdit: val });
}
render() {
return (
<div>
<div className="headerBar">
{ /* Render EditToggle */ }
{ /* Render ColorChanger */ }
{ /* Render SizeChanger */ }
{ /* Render FamilyChanger */ }
</div>
<div className="textArea">
{ /* Render TextContainer */ }
</div>
</div>
)
}
}
export default App;In this step, we will render our imported components in App.js.
- Open
src/App.js. - Render the
EditTogglecomponent where it says{ /* Render EditToggle */ }:- Add a prop called
updatethat is equal to theupdateEditStatusmethod.
- Add a prop called
- Render the
ColorChangercomponent where it says{ /* Render ColorChange */ }:- Add a prop called
updatethat is equal to theupdateColormethod. - Add a prop called
allowEditthat is equal to the value ofallowEditon state.
- Add a prop called
- Render the
SizeChangercomponent where it says{ /* Render SizeChanger */ }:- Add a prop called
updatethat is equal to theupdateSizemethod. - Add a prop called
allowEditthat is equal to the value ofallowEditon state.
- Add a prop called
- Render the
FamilyChangercomponent where it says{ /* Render FamilyChanger */ }:- Add a prop called
updatethat is equal to theupdateFamilymethod. - Add a prop called
allowEditthat is equal to the value ofallowEditon state.
- Add a prop called
- Render the
TextContainercomponent where it says{ /* Render TextContainer */ }:- Add a prop called
fontColorthat equalsfontColoron state. - Add a prop called
fontSizethat equalsfontSizeon state. - Add a prop called
fontFamilythat equalsfontFamilyon state.
- Add a prop called
src/App.js
import React, { Component } from 'react';
// Components
import EditToggle from './components/EditToggle';
import ColorChanger from './components/ColorChanger';
import SizeChanger from './components/SizeChanger';
import FamilyChanger from './components/FamilyChanger';
import TextContainer from './components/TextContainer';
class App extends Component {
constructor() {
super();
this.state = {
fontColor: 'black',
fontSize: 12,
fontFamily: 'monospace',
allowEdit: 'true'
};
this.updateColor = this.updateColor.bind( this );
this.updateSize = this.updateSize.bind( this );
this.updateFamily = this.updateFamily.bind( this );
this.updateEditStatus = this.updateEditStatus.bind( this );
}
updateColor(val) {
this.setState({ fontColor: val });
}
updateSize(val) {
this.setState({ fontSize: val });
}
updateFamily(val) {
this.setState({ fontFamily: val });
}
updateEditStatus(val) {
this.setState({ allowEdit: val });
}
render() {
return (
<div>
<div className="headerBar">
<EditToggle update={ this.updateEditStatus } />
<ColorChanger update={ this.updateColor } allowEdit={ this.state.allowEdit } />
<SizeChanger update={ this.updateSize } allowEdit={ this.state.allowEdit } />
<FamilyChanger update={ this.updateFamily } allowEdit={ this.state.allowEdit } />
</div>
<div className="textArea">
<TextContainer
fontColor={ this.state.fontColor }
fontSize={ this.state.fontSize }
fontFamily={ this.state.fontFamily } />
</div>
</div>
)
}
}
export default App;In this step, we will update our select elements in the EditToggle, ColorChanger, FamilyChanger, and SizeChanger components to use an onChange that calls the update prop with the value of the select element. We will also disable the select element if the value of allowEdit is "false".
- Open
EditToggle,ColorChanger.js,FamilyChanger.js, andSizeChanger.jsfromsrc/components/. - Locate the
selecttag, in all four files, and add anonChangeprop:- The
onChangeshould use an arrow function to capture theevent. - Inside the arrow function call the
updateprop with the value of the target from theevent. - Parse Int the value of the target when in
SizeChanger.js.
- The
- Locate the
selecttag, inColorChanger,FamilyChanger, andSizeChanger, and add adisabledprop:- The
selectelement should bedisabledifallowEditfrom props is equal to"false".
- The
src/components/EditToggle.js
return (
<select className="dropDownContainer ml0" onChange={ (e) => this.props.update(e.target.value) }>
<option value="true"> Allow Edit </option>
<option value="false"> Disable Edit </option>
</select>
) src/components/ColorChanger.js
return (
<select className="dropDownContainer" onChange={ (e) => this.props.update(e.target.value) } disabled={ this.props.allowEdit === "false" }>
<option value="black"> Black </option>
<option value="blue"> Blue </option>
<option value="green"> Green </option>
</select>
) src/components/FamilyChanger.js
return (
<select className="dropDownContainer" onChange={ (e) => this.props.update(e.target.value) } disabled={ this.props.allowEdit === "false" }>
<option value="monospace"> Monospace </option>
<option value="arial"> Arial </option>
<option value="courier"> Courier </option>
</select>
) src/components/SizeChanger.js
return (
<select className="dropDownContainer" onChange={ (e) => this.props.update( parseInt(e.target.value) ) } disabled={ this.props.allowEdit === "false" }>
<option value="12"> 12 </option>
<option value="13"> 13 </option>
<option value="14"> 14 </option>
</select>
)Now we have everything set up to be able to edit the look of our text. Our last step is to connect our styling in the TextContainer components to the props being passed to it so they will reflect the changes we make.
- Open
TextContainer.jsfromsrc/components/. - Bind the
updateTextmethod tothisin theconstructormethod. - In the
textareatag there is astyleprop, this is where we need to add the styling that's being passed to this component through props.- Uncomment the
styleprop. - Set
fontFamily,fontSizeandcolorequal to the appropriate props values.
- Uncomment the
src/components/TextContainer.js
import React, { Component } from 'react';
export default class TextContainer extends Component {
constructor() {
super()
this.state = {
text: ''
}
this.updateText = this.updateText.bind(this)
}
updateText(e) {
this.setState({
text: e.target.value
})
}
render() {
return (
<div className="textContainer">
<textarea
style={ { color: this.props.fontColor, fontFamily: this.props.fontFamily, fontSize: this.props.fontSize } }
onChange={this.updateText}
value={this.state.text}
placeholder='This is where your text will be!'
cols="90"
rows="30">
</textarea>
</div>
)
}
}If you see a problem or a typo, please fork, make the necessary changes, and create a pull request so we can review your changes and merge them into the master repo and branch.
© DevMountain LLC, 2017. Unauthorized use and/or duplication of this material without express and written permission from DevMountain, LLC is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to DevMountain with appropriate and specific direction to the original content.




