简体   繁体   中英

Should renderItem of FlatList be wrapped with react useCallback hook?

const Component = React.memo(props => {
  const { url } = props;

  const keyExtractor = useCallback(item => item.id, []);

  const handleClick = useCallback(() => {
    Linking.openURL(url);
  }, [url]);

  const renderItem = useCallback(({ item }) => {
    return (
      <TouchableOpacity onPress={handleClick}>
        <Text>Test</Text>
      </TouchableOpacity>
    );
  }, [handleClick]);

  return (
    <FlatList
      data={data}
      keyExtractor={keyExtractor}
      renderItem={renderItem}
    />
  );
});

Just like the code above.

If the renderItem function is wrapped with a useCallback hook. it must check if the handleClick function reference is changed because the handleClick function may be changed if url is different. and it looks a little strange.

I wonder if there is a significant difference in the performance of using useCallback to wrap renderItem .

What is the best practice of using hooks for renderItem functions? Thanks

Because you already use React.memo the Component will not be executed unless url changes, if url changes the useCallback will re create the functions anyway so you can leave them out provided that is the only prop that can change.

Here is some code demonstrating this, you can re render App as much as you want but it won't re render other components unless you change url.

 const SubComponent = ({ onClick }) => { console.log('sub component render'); return <button onClick={onClick}>log url</button>; }; const PureComponent = React.memo(function PureComponent({ url, }) { console.log('pure component render', url); //even if I do React.useCallback(fn,[url]) that would mean // it creates onClick when url changes but it would already // only create onClick when url changes because memo will // memoize the component result and not execute PureComponent // unless the url changes const onClick = () => console.log('url is', url); return <SubComponent onClick={onClick} />; }); const App = () => { const [, reRenderApp] = React.useState({}); const [url, setUrl] = React.useState( new Date().toUTCString() ); console.log('rendering App'); return ( <div> <button onClick={() => reRenderApp({})}> re render app </button> <button onClick={() => setUrl(new Date().toUTCString())} > set url </button> <PureComponent url={url} /> </div> ); }; ReactDOM.render(<App />, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

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