React.useMemo in class component
Asked Answered
P

2

25

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

Parasympathetic answered 21/5, 2020 at 8:42 Comment(1)
See SelectorsIzzy
C
21

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.

Ciceronian answered 21/5, 2020 at 10:52 Comment(3)
Thank you @Ciceronian for your answerParasympathetic
I have been searching for it for a while!Oldie
I've found that memoize function is much easier to use and closer to useMemo, than componentDidMount / componentDidUpdate. Pay attention to memoize techinque described here - reactjs.org/blog/2018/06/07/…Allister
G
3

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);
  }
}
Granddaddy answered 21/5, 2020 at 9:27 Comment(2)
Hi @resolritter. Thank you for the answer but I was wondering about memoization, not state changing based on props)Parasympathetic
Notice the props.values !== state.values; you're only regenerating the childrenIds in case the props changes, so it effectively is memoization (it keeps track of the last input and doesn't recompute unless the input changes).Granddaddy

© 2022 - 2024 — McMap. All rights reserved.