Remember when we looked at different ways of creating React component in the first page of this tutorial, we said there are things that component extending can do that a function
component cannot do? Well state is one of them. React.Component
can have states but function
cannot have states.
Note: There's a new feature in React called hooks that let's us use state within function component but that's still in alpha so if we want to use state right now on a component we still need to use React.Component
Below is a simple component that has a state.
state
is just an object. If you notice the constructor, we initialized the state with {counter: 0}
. And we used the state inside the return
of the render
function as {this.state.counter}
.
We initialized the state
in the constructor but how do we update it? For eg. in the above example how do we change the counter
to lets say 1? For that React provides a function called setState
. You should always use setState
function to change state
and never mutate it directly.
- //❌ NEVER DO THIS
- this.state.counter = 2;
- // ✅ ALWAYS DO THIS
- this.setState({
- counter: 2
Let's look deeper into setState
function. First argument of setState
function can take either a new state object or a function. It also has a optional second argument, which is a callback which is executed when the state is updated.
The way setState
updates the state is:
- If the first argument of the
setState
function is an object, it merges the currentstate
object with whatever you passed to thesetState
function. For example:
- state = { a: 1, b: 2, c: 3} //current state
- this.setState({ a: 3 }); //we call setState with just one key value pair
- //it will **merge** the initial state with the object passed to setState
- //as a result only the value for that one key is updated
- state = { a: 3, b: 2, c: 3 } //state after setState is flushed
One thing you must know about setState
function is that it may be asynchronous. So do not rely on it to update the state immediately. This is not a bug, it's by design. If you want to read up on the design decision behind setState
call being asynchonous, here's a .
Since setState
can be asynchronous below code will not give you the right result because by the time we console.log
the state.counter
value, it won't be updated.
- //❌ WRONG RESULT. Do not rely on setState to be synchronous
- console.log(this.state.counter);//prints 0
- this.setState({
- counter: this.state.counter + 1
- }); //this is asynchronous call
- console.log(this.state.counter);//still prints 0
Also if you want to update state
using the current state value always use the updater function inside setState
instead of passing object. For example below code will not work.
I know we discussed several things about state
and it must be overwhelming. Let's just recap the rules:
- Never mutate
this.state
directly. Always usethis.setState
to update thestate
. - If your new
state
depends on the oldstate
then usethis.setState(function(currentState){ .. })
construct.
Props and State
Since we now have looked into both state
and props
how are they different and how are they similar?
The difference between state
and props
is that state
is owned by the component itself while props
is something that is passed down to the component by it's parent.
And the similarity (sort of) is that React automatically re-renders your component when either the component's state
changes or when the component's props
changes.
Your component's render
function is a function of both state
and props
meaning it defines what your component should look like given the state
and props
. It should be pure function in a sense that if the component has same state
and props
it should render exactly same content no matter how many times it's called and shouldn't have any side effects.