生成带有动态参数的备注化更改处理程序

通常使用以下函数来生成更改处理程序:

let onChange =
    (key) => (value) => {
        setState((ps) => ({
            ...ps,
            [key]: value,
        }));
    };

并使用像:

<TextField
 value={state.firstName}
 onChange={onChange("firstName")}
/>
<TextField
 value={state.lastName}
 onChange={onChange("lastName")}
/>

Assume we are using React hooks. The problem above is that onChange creates new function on each render, hence, if you change firstName both TextField components will be rerendered since a new change handler is passed to both. This will happen even if TextField is a component created using react.memo with default comparison.

How to generate change handlers this way such that the onChange function remains same for same text field component across rerenders using React Hooks?

评论
  • 请勿打扰
    请勿打扰 回复

    The answer lies in combining useCallback and a memoization helper like fast-memoize say. If you use this change handler:

      let onChange = React.useCallback(
        memoize((key) => (value) => { // e.g. import memoize from "fast-memoize";
          setState((ps) => ({
            ...ps,
            [key]: value,
          }));
        }),
        []
      );
    

    and create TextField components using React.memo with default comparison, changing firstName will not cause re render of another TextField anymore.

    用法类似,例如:

    <TextField
     value={state.firstName}
     onChange={onChange("firstName")}
    />
    

    注意:

    Simply using memoize wouldn't work, as on next render it would invoke memoize from fresh like this:

    let memoized = memoize(fn)
    
    memoized('foo', 3, 'bar')
    memoized('foo', 3, 'bar') // cache hit
    
    memoized = memoize(fn); // without useCallback this would happen on next render 
    
    // Now the previous cache is lost