React.useMemo in class component

Velidan picture Velidan · May 21, 2020 · Viewed 21.3k times · Source

Is there a way to use this hook or some its analogue of the React API in the case of a class component?

I'm wondering, should I use some third party memo helpers in the case of a class component (eg. lodash memo, memoizeOne, etc.) or there is exist some official react API way for class components.

Thanks for any help.

P.S.

I want to generate uuid in the case of changed Children.

with SFC component I could use useMemo like this

const keyValue = useMemo(() => uuid()(), [children])

But how to achieve the same for class-based components without any thirdparty, etc.
P.P.S. I'm not using Redux, etc. only pure React.js

Answer

ford04 picture ford04 · May 21, 2020

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.