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
.
Live Example: click here
fork
andclone
this repository.cd
into the project directory.- Run
npm install
. - Run
npm start
afternpm install
has finished, to start the development server.
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.
Note: We are using a
class
component for this example to practice some concepts related toclass
components.
- Open
src/App.js
. - Create a
constructor
method where it says// constructor
:- This method should call
super()
. - This method should create an initial state object with the following properties:
{ fontColor: 'black', fontSize: '12px', 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
updateColor
method that takes a parameter calledval
where it says// updateColor
:- Use
setState
to updatefontColor
toval
.
- Use
- Create an
updateSize
method that takes a parameter calledval
where it says// updateSize
:- Use
setState
to updatefontSize
toval
.
- Use
- Create an
updateFamily
method that takes a parameter calledval
where it says// updateFamily
:- Use
setState
to updatefontFamily
toval
.
- Use
- Create an
updateEditStatus
method that takes a parameter calledval
where it says// updateEditStatus
:- Use
setState
to updateallowEdit
toval
.
- 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
this
to theupdateColor
,updateSize
,updateFamily
, andupdateEditStatus
methods at the bottom of theconstructor
method.
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
EditToggle
component where it says{ /* Render EditToggle */ }
:- Add a prop called
update
that is equal to theupdateEditStatus
method.
- Add a prop called
- Render the
ColorChanger
component where it says{ /* Render ColorChange */ }
:- Add a prop called
update
that is equal to theupdateColor
method. - Add a prop called
allowEdit
that is equal to the value ofallowEdit
on state.
- Add a prop called
- Render the
SizeChanger
component where it says{ /* Render SizeChanger */ }
:- Add a prop called
update
that is equal to theupdateSize
method. - Add a prop called
allowEdit
that is equal to the value ofallowEdit
on state.
- Add a prop called
- Render the
FamilyChanger
component where it says{ /* Render FamilyChanger */ }
:- Add a prop called
update
that is equal to theupdateFamily
method. - Add a prop called
allowEdit
that is equal to the value ofallowEdit
on state.
- Add a prop called
- Render the
TextContainer
component where it says{ /* Render TextContainer */ }
:- Add a prop called
fontColor
that equalsfontColor
on state. - Add a prop called
fontSize
that equalsfontSize
on state. - Add a prop called
fontFamily
that equalsfontFamily
on 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.js
fromsrc/components/
. - Add
props
as a parameter to the component's function. - Locate the
select
tag, in all four files, and add anonChange
prop:- The
onChange
should use an arrow function to capture theevent
. - Inside the arrow function call the
update
prop with the value of the target from theevent
. - Parse Int the value of the target when in
SizeChanger.js
.
- The
- Locate the
select
tag, inColorChanger
,FamilyChanger
, andSizeChanger
, and add adisabled
prop:- The
select
element should bedisabled
ifallowEdit
from props is equal to"false"
.
- The
src/components/EditToggle.js
return (
<select
className="dropDownContainer ml0"
onChange={ (e) => 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) => props.update(e.target.value) }
disabled={ 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) => props.update(e.target.value) }
disabled={ 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) => props.update( parseInt(e.target.value) ) }
disabled={ props.allowEdit === "false" }
>
<option value="12px"> 12 </option>
<option value="13px"> 13 </option>
<option value="14px"> 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.js
fromsrc/components/
. - Bind the
updateText
method tothis
in theconstructor
method. - In the
textarea
tag there is astyle
prop, this is where we need to add the styling that's being passed to this component through props.- Uncomment the
style
prop. - Set
fontFamily
,fontSize
andcolor
equal to the appropriate props values.
- Uncomment the
src/components/TextContainer.js
import React, { Component } from 'react';
export default class TextContainer extends Component {
constructor(props) {
super(props);
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="Start typing your thoughts here!"
cols="90"
rows="30"
/>
</div>
);
}
}