States and Props in React
Components are everywhere in react and props and states are updating in every second.
States
States are the properties of the components and the speciality of the state is when state is changing the component is re-render if needed. There are two ways of initialise states as follows.
- Inside the constructor — recommended method.
import React, {Component} from "react";class App extends Component {
constructor(props) {
super(props);
this.state = { name: "Yashod" };
}
render(){
return <div>App</div>;
}
}
- Inside the class
import React, {Component} from "react";class App extends Component {
state = { name: "Yashod" };
render(){
return <div>App</div>;
}
}
setState() function
setState is used to update the state value as follows and most important thing is that it is asynchronous.
- Standard method.
import React, {Component} from "react";class App extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment(oldCount) {
this.setState({ count: oldCount + 1});
} render(){
return (
<div>
<p>{this.state.count}</p>
<button onClick = {() => this.increment(this.state.count)}>
Increment
</button>
</div>
);
}
}
Important : If previous states or props used to updated the state it is not good to use previous setState method.
import React, {Component} from "react";class App extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment() {
this.setState((prevState) => ({
count: prevState.count + 1
})
);
}render(){
return (
<div>
<p>{this.state.count}</p>
<button onClick = {() => this.increment()}>
Increment
</button>
</div>
);
}
}
- Using previousStates and props.
If the state is continuously updating or the current state depends of previous state it is needed to use this method.
this.setState(
(prevState, props) => ({
// code
})
)
Following is an Example
import React, {Component} from "react";class App extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment() {
this.setState(
(prevState, props) => ({
count: prevState.count + 1
})
);
}render(){
return (
<div>
<p>{this.state.count}</p>
<button onClick = {() => this.increment()}>
Increment
</button>
</div>
);
}
}
- Using callbacks
setState is asynchronous and rest of the code is not wait until it completes. In some cases we have to wait until it completes for that we have to use callbacks as follows.
this.setState(
{ count: 1},
() => console.log("State is updated)
);
Console log will execute after the state is set. Likewise we can use any function there which should be executed after setting the state.
Common mistakes in setState function.
- Make several setStates in one function which can be combined.
// Wrong
someFunc() {
setState({name: "Amal"});
setState({age: 20});
setState({email: "amal@gmail.com"});
}
Above function will lead to more component update life cycles which will drop the performance. Hence following can be used.
// Correct
someFunc() {
setState({
name: "Amal",
age: 20,
email: "amal@gmail.com"
});
}
- Using setState in constructor, render. — setState method is not used in constructor or render method.
- Using setState in componentDidUpdate without condition. — This will lead to infinite loop as well.
// Infinite Loop
componentDidUpdate(prevProps, preState, snapshot) {
setState({ name: "Amal" });
}// Solution
componentDidUpdate(prevProps, preState, snapshot) {
if (prevProps.name != this.state.name) {
setState({ name: "Amal" });
}
}
- Callbacks are not used when newly set state is needed. — If a value is needed just after setting the state those should be go under callback inside the setState.
Props
Props are read only properties which are passed from parent to child as follows.
If you are not familiar with lists and keys used in following example please read following.
import React, { Component } from "react";class List extends Component {
students = [
{ id: 1, name: "Amal", age: 25 },
{ id: 2, name: "Mark", age: 32 },
{ id: 3, name: "Sithum", age: 28 },
{ id: 4, name: "Tony", age: 30 }
];
studentList = this.students.map(student => (
<Student key={student.id}
name={student.name}
age={student.age} />
));
render() {
return <div>{this.studentList}</div>;
}
}const Student = props => {
return (
<div>
<h3>
{props.name} is {props.age} years old
</h3>
</div>
);
};export default List;
Props are passed from the List component to Student component as shown in the example.
Can we pass functions to the child? Yes you can.
We can pass functions as props as well.
import React, { Component } from "react";class List extends Component {
students = [
{ id: 1, name: "Amal", age: 25 },
{ id: 2, name: "Mark", age: 32 },
{ id: 3, name: "Sithum", age: 28 },
{ id: 4, name: "Tony", age: 30 }
]; anyFunction = () => {
// code
}
studentList = this.students.map(student => (
<Student key={student.id}
name={student.name}
age={student.age}
anyFunc={this.anyFunction}/>
));
render() {
return <div>{this.studentList}</div>;
}
}const Student = props => {
if (sth) {
props.anyFunc();
} return (
<div>
<h3>
{props.name} is {props.age} years old
</h3>
</div>
);
};export default List;
References
Hopefully this is helpful.
If you have found this helpful please hit that 👏 and share it on social media :).