【问题标题】:Should renderItem of FlatList be wrapped with react useCallback hook?FlatList 的 renderItem 是否应该用 react useCallback 钩子包裹?
【发布时间】:2020-03-23 19:48:33
【问题描述】:
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}
    />
  );
});

就像上面的代码。

如果renderItem 函数被useCallback 钩子包裹。它必须检查handleClick 函数引用是否已更改,因为如果url 不同,handleClick 函数可能会更改。而且看起来有点奇怪。

不知道用useCallback包裹renderItem在性能上是否有显着差异。

renderItem 函数使用钩子的最佳做法是什么?谢谢

【问题讨论】:

    标签: javascript reactjs react-native react-hooks


    【解决方案1】:

    因为您已经使用 React.memo,除非 url 更改,否则不会执行组件,如果 url 更改,useCallback 无论如何都会重新创建函数,因此您可以将它们排除在外,前提是这是唯一可以更改的道具。

    这里有一些代码演示了这一点,您可以根据需要重新渲染 App,但除非您更改 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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-04
      • 2022-08-19
      • 1970-01-01
      • 2019-09-21
      • 1970-01-01
      • 2022-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多