React State
- State is similar to props, but it is private and fully controlled by the component.
- State object is initialized in the constructor
- State object can be referred anywhere in the component by using the
this.state.propsname
eg.,this.state.name, this.state.duration
- To change the value in the state object, use the
this.setState()
method. When the value in the state object changes, the component will re-render
class Course extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "Python",
duration: 30,
fee: 350,
trainer: "Girish"
};
}
changeCourse = (event) => {
this.setState({name: event.target.value});
}
changeTrainer = () => {
this.setState({trainer:"Krishna"});
}
render() {
return (
<div>
<h1>Course Name: {this.state.name}</h1>
<p>
Course Duration: {this.state.duration} <br/>
Course Fee: {this.state.fee} <br/>
Course Trainer: {this.state.trainer} <br/>
</p>
Course Name: <input type="text" onChange={this.changeCourse}/> <br/>
<button onClick={this.changeTrainer}>Change Trainer</button> <br/>
</div>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'));
Do Not Modify State directly, Instead, use setState()
. Bellow is the sample background color change example using setState() while toggling the button. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
class ToggleColor extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
this.state.color = "";
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
// console.log(this.state.isToggleOn);
if(!this.state.isToggleOn)
{
this.setState({color : "blue"})
}
else
{
this.setState({color : "yellow"})
}
}
render() {
var myStyle = {
backgroundColor: this.state.color}
return (
<div>
<h1 style= {myStyle}>background color </h1>
<button onClick={this.handleClick}> {this.state.isToggleOn ? 'yellow' : 'blue'}
</button>
</div>
);
}
}
ReactDOM.render(
<ToggleColor />,
document.getElementById('root')
);
React Events
- React events are named using camelCase, rather than lowercase. eg
handleClick()
- With JSX you pass a function as the event handler, rather than a string. eg
onClick={display}
- In JavaScript, class methods are not bound by default. For class methods in React,
this
keyword should represent the component that owns the method. Using arrow functions,this
will always represent the object that defined the arrow function.
With Normal display() method inside Course Class Component
class Course extends React.Component {
constructor(props) {
super(props)
}
display() {
alert(this);
}
render() {
return (
<button onClick={this.display}>Display Alert</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
With arrow function display inside Course Class Component
class Course extends React.Component {
constructor(props) {
super(props)
}
display= () => {
alert(this);
}
render() {
return (
<button onClick={this.display}>Display Alert</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
- If you have to use regular javascript functions instead of arrow functions then you have to bind
this
to the component instance using thebind()
method
class Course extends React.Component {
constructor(props) {
super(props)
this.display = this.display.bind(this)
}
display() {
alert(this);
}
render() {
return (
<button onClick={this.display}>Display Alert</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
Passing Arguments to Event Handlers
- Create anonymous arrow function and call the function with arguments in the callback
class Course extends React.Component {
constructor(props) {
super(props)
}
display(data) {
alert("Value: "+ data);
}
render() {
return (
<button onClick={()=>this.display("React")}>Display Alert</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
- Bind the event handler display() to
this
.
class Course extends React.Component {
constructor(props) {
super(props)
}
display(data) {
alert("Value: "+ data);
}
render() {
return (
<button onClick={this.display.bind(this, "React")}>Display Alert</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
With an arrow function, we have to pass the event object manually. The “e” argument representing the React event will be passed as a second argument after the first argument.
class Course extends React.Component {
constructor(props) {
super(props)
}
printValue(value, event) {
alert("Value: " + value + " " + "\n" + "Event Type: " + event.type);
}
render() {
return ( // This syntax ensures 'this' is bound within printValue
<button onClick={(e) => this.printValue("React JS", e)}>Submit</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
With bind any further arguments are automatically forwarded
class Course extends React.Component {
constructor(props) {
super(props)
}
printValue(value, event) {
alert("Value: " + value + " " + "\n" + "Event Type: " + event.type);
}
render() {
return (
<button onClick={this.printValue.bind(this, "React")}>Print Value with Bind</button>
);
}
}
ReactDOM.render(<Course />, document.getElementById('root'))
References
- https://reactjs.org/docs/state-and-lifecycle.html
- https://reactjs.org/docs/handling-events.html
- https://reactjs.org/docs/conditional-rendering.html
Learn More about React features in the next upcoming blog articles
Happy Learning!