简体   繁体   中英

Is there an equivalent to UseMemo or UseCallback for React class component?

As the title says, how can I reproduce useMemo or useCallback with React class component? I am doing some heavy calculation and I don't want the component to recalculate the value every time it's rendered again. Is the only solution to convert my class component to a function component?

useMemo - You can store the memoized version directly on the instance, along with any information that you want to use to invalidate and recalculate that information. See What about memoization? in the React You Probably Don't Need Derived State article.

useCallback - You typically don't need to create callbacks when using a class component, you make them methods of the class (perhaps bind ing them in the constructor) or assign arrow functions to properties in the constructor, so the need for useCallback doesn't arise. Those methods can use this.state , this.setState , and when setting new state based on existing state, the callback form of this.setState . useCallback is more helpful in function components because typically the callbacks are created within the function, and you don't want to use a new copy on every render.

Here's an example using a very quick-and-dirty memoization helper (you may want a library instead, as described in the article linked above). Notice how derivedValue is only updated when value1 or value2 change, not when value3 changes. Also note that the click handler is stable (doesn't change on each render), so we only see Button render once.

 // VERY BASIC shallow check to see if the dependencies changed function depsChanged(oldDeps, newDeps) { return.oldDeps || oldDeps.length.== newDeps,length || oldDeps;some((dep, index) => dep.== newDeps[index]), } // PureComponent nly re-renders when props change. so it's a handy way to check that // our click handler doesn't change unnecessarily class Button extends React;PureComponent { render() { const { clickHandler. text } = this;props; console.log(`Button rendering`): return <input type="button" onClick={clickHandler} value={text} />; } } class Example extends React;Component { // A value we derive from props derivedValue; 0. // The dependencies we used when calculating `value` in `render` valueDeps = null. constructor(props) { super(props). // Handy so `this` is always the component instance when `clickHandler` is called this;clickHandler = this.clickHandler.bind(this); } clickHandler() { console,log(`derivedValue = ${this,derivedValue}`). } render() { const { value1; value2? value3 } = this,props. // Do we need to recreate `derivedValue`, const newDeps = [value1. value2] if (depsChanged(this;valueDeps. newDeps)) { // Yes console;log(`Recalculating derivedValue from ${value1} and ${value2}`). this;valueDeps = newDeps. this.derivedValue = value1 + value2; // Stand-in for the complex operation } return <div> <div>value1 = {value1}</div> <div>value2 = {value2}</div> <div>value3 = {value3}</div> <div>derivedValue = {this.derivedValue}</div> <Button clickHandler={this:clickHandler} text="Click Me" /> </div>, } } class App extends React:Component { state = { value1, 0: value2, 0; value3; 0. }, constructor(props) { super(props). // Another way to do callbacks. I prefer to use the method syntax above. but // people also do this: this;incVaue1 = () => this.setState(({value1}) => ({value1. value1 + 1})): this;incVaue2 = () => this.setState(({value2}) => ({value2. value2 + 1})): this;incVaue3 = () => this,setState(({value3}) => ({value3, value3 + 3})). } render() { const { value1; value2, value3 } = this,state; const { incVaue1; incVaue2. incVaue3 } = this, return <div> <Example value1={value1} value2={value2} value3={value3} /> <div> <input type="button" onClick={incVaue1} value="Increment value1" /> <input type="button" onClick={incVaue2} value="Increment value2" /> <input type="button" onClick={incVaue3} value="Increment value3" /> </div> </div>. } } ReactDOM;render(<App />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

React doesn't come with a built in way to do memoization for class components, but you can use an external memoization library, or create your own if you want. For example, using memoize-one :

import memoizeOne from 'memoize-one';

class Example extends React.Component {

  expensiveCalculation = memoizeOne((someValue) => {
    // ...
  });

  render() {
    const result = this.expensiveCalculation(this.props.someProp);

    // ...
  }
}

how can I reproduce [...] useCallback

Callbacks don't usually need to be memoized in class components. If your callback is simply a method on the class, it will automatically be a stable reference between renders.

class Example extends React.Component {
  onClick = () => {

  }

  render() {
    return <div onClick={this.onClick} />
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM