A common footgun in React projects is
derived state,
which means basing state on props. This can be directly copying props into
state, or deriving state from props with some extra logic.
This often causes trouble because once the state is set based on props, it won’t
be updated by subsequent updates to props. This is after all the purpose of
props and state in React: props are clean and stateless, and state is of course
stateful.
To give a minimal example, here’s a parent component with a child component in
JSX:
<Parent>
<Child foobar={100}>
</Parent>
The parent is passing a value of 100 for the child’s foobar prop.
The child component implementation might look like this:
class Child extends React.Component {
state = {
derivedThing: this.props.foobar * 2
}
}
The derivedThing state on Child is derived state as it’s derived from the
foobar prop that is passed in.
This is likely to cause problems if the parent component does an initial render
with a default value and then a subsequent render with a new value, for example
after fetching some data from the server.
For example, if the parent is a functional component it might look like this:
(This has a bug due to derived state!)
const Parent = () => {
const [foobar, setFoobar] = useState(0)
useEffect(() => {
fetch("example.com/foobar.json")
.then(res => res.json())
.then(json => setFoobar(json.foobar))
, [])
return (
<div>
<Child foobar={foobar}>
</div>
)
}
This will lead to a bug:
- The Parent initialises
foobar to 0
- The Parent renders Child with the
foobar prop as 0
- The Child initialises its
derivedThing state to 0
- The Parent’s
useEffect call fetches the real value for foobar , e.g. 100
- The Parent re-renders the Child with the
foobar prop as 100
- The Child has already initialised its derived state, so it ignores the new prop value.
- The Child is now stuck with its
derivedThing state as 0 .
This is quite a common footgun in React, which is why it’s best to avoid derived
state whenever possible.
It might help to remember the rule of thumb that state is for interactivity.
In other words, state is not for general variables in the program, it’s for
interactivity with a human user, with state that will change over the course of
the React process lifetime due to user actions.
View post:
Avoid deriving state from props in React
|