React hooks useCallback with parameters inside loop

前端 未结 1 1095
野的像风
野的像风 2020-12-31 00:55

I\'m trying to learn about the hooks functionality, however I can\'t quite seem to figure out how I\'m supposed to use the function useCallback properly. As far

相关标签:
1条回答
  • 2020-12-31 01:09

    The simple answer here is, you probably shouldn't use useCallback here. The point of useCallback is to pass the same function instance to optimized components (e.g. PureComponent or React.memoized components) to avoid unnecessary rerenders.

    You're not dealing with optimized components in this case (or most cases, I'd suspect) so there's not really a reason to memoize callbacks like with useCallback.


    Supposing the memoization is important, though, the best solution here is probably to use a single function instead of five: instead of a unique function for each button carries the key by closure, you can attach the key to the element:

    <button data-key={key}>{key}</button>
    

    And then read the key from the event.target.dataset["key"] inside a single click handler:

    const Example = (props) => {
      // Single callback, shared by all buttons
      const onClick = React.useCallback((e) => {
        // Check which button was clicked
        const key = e.target.dataset["key"]
        console.log("You clicked: ", key);
      }, [/* dependencies */]);
      
      return(
        <div>
          {
            _.times(5, (key) => {
              return (
                <button data-key={key} onClick={onClick}>
                  {key}
                </button>
              );
            })
          }
        </div>
      );
    };
    console.log("hello there");
    
    ReactDOM.render(<Example/>, document.getElementById('root'));
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
    
    <div id='root'>
    </div>


    All that being said, it is possible to memoize multiple functions in a single hook. useCallback(fn, deps) is equivalent to useMemo(() => fn, deps), and useMemo can be used to memoize multiple functions at once:

    const clickHandlers = useMemo(() => _.times(5, key => 
      () => console.log("You clicked", key)
    ), [/* dependencies */]);
    

    const Example = (props) => {
      const clickHandlers = React.useMemo(() => _.times(5, key => 
        () => console.log("You clicked", key)
      ), [/* dependencies */])
      
      return(
        <div>
          {
            _.times(5, (key) => {
              return (
                <button onClick={clickHandlers[key]}>
                  {key}
                </button>
              );
            })
          }
        </div>
      );
    };
    console.log("hello there");
    
    ReactDOM.render(<Example/>, document.getElementById('root'));
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
    
    <div id='root'>
    </div>

    Perhaps there's a case where that's useful, but in this case I would either leave it alone (and not worry about the optimization) or else use a single handler for each button.

    0 讨论(0)
提交回复
热议问题