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
函数引用是否已更改,因为如果handleClick
不同,则url
函数可能会更改。看起来有点奇怪。
我想知道使用useCallback
来包装renderItem
的性能是否有显着差异。
对renderItem
函数使用钩子的最佳实践是什么?谢谢
答案 0 :(得分: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>