React.useMemo in class component
Use getDerivedStateFromProps. The official React docs mentions this technique here.
As of version 16.3, the recommended way to update state in response to props changes is with the new static getDerivedStateFromProps lifecycle.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
values: props.values,
childrenIds: []
};
}
static getDerivedStateFromProps(props, state) {
if (props.values !== state.values) {
return {
values: props.values,
childrenIds: generateIds(props.values)
};
}
return null;
}
render() {
return JSON.stringify(this.state.childrenIds);
}
}
As per React docs:
If you want to re-compute some data only when a prop changes, use a memoization helper.
The docs use memoizeOne
as library, so this would be a good choice. You can also change keyValue
as part of a side effect with componentDidUpdate
:
componentDidMount() {
this.keyValue = uuid()()
}
componentDidUpdate(prevProps) {
if (this.props.children !== prevProps.children) {
this.keyValue = uuid()()
// alternative: store keyValue as state to trigger re-render
}
}
getDerivedStateFromProps
can be an alternative for rare cases, other options are usually preferred.
Why useMemo
is not a good choice with uuid()
You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. (docs)
A memoized value const keyValue = useMemo(() => uuid()(), [children])
might be re-calculated despite children
being the same in React future. This case could lead to inconsistencies, if uuid()
returns a new id, but children
haven't changed.
For function components an alternative is useRef
with useEffect
depending on your use case.