如何在 React 中编写由 useCallback 优化的 onClick(带参数)?
how to write onClick (with arguments) optimized by useCallback in React?
我需要实现一个长列表,长列表中的每一项在onClick的时候都会触发一个新的函数,因为这个函数在每次渲染的时候都是不变的,所以想用useCallback优化一下,这个返回了function Fn需要传参,onClick中是否应该使用bind传参?
const func = useCallback((num) => setIndex(num), [])
// myComponent
<TableItem onClick = { func.bind(null, index) } />
这是我的第一个问题,如果有不对的地方请多多包涵,谢谢
你需要在useCallback中设置第二个参数,这将防止多次渲染。
也就是说,如果你想在组件启动时设置它,你可以设置
useCallback((num => setIndex(num)), [])
注意[],表示只在开始渲染,如果想在任何变量变化时更新,可以设置[variablename, ...]
另外,我觉得你不需要func.bind,你可以只设置
<Component onClick={func}/>
编辑:我误解了这个问题。
如果你想在 onClick 中发送一个参数,你可以这样设置
const func = useCallback((num => setIndex(num)), [])
<Component onClick={()=>func(yourParam)}/>
通过这种方式,您的 onClick 将始终使用该功能,但它允许您可以在任何地方设置的参数
如果将回调传递给多个组件,则可以按以下方式使用 useCallback:
//make Counter a pure component (only re renders if something changed)
const Counter = React.memo(function Counter({
counter,
up,
index,
}) {
// ok to do onClick={new=>'function'} because we do not pass
// onClick to sub components unless counter changes
console.log('rendering index:', index);
return (
<button onClick={() => up(index)}>{counter}</button>
);
});
const App = () => {
//fixed amount of items that does not re order so can use index
// in key, do not use index as key when you don't have fixed
// amount of items or re order the list.
const [counters, setCounters] = React.useState([0, 0]);
const up = React.useCallback(
(index) =>
//pass callback to setCounters so counters is not
// a dependency of useCallback
setCounters((counters) =>
counters.map((counter, i) =>
i === index ? counter + 1 : counter
)
),
[]//empty dependency, only created when App mounts
);
return (
<ul>
{counters.map((counter, index) => (
<Counter
up={up}
counter={counter}
key={index}
index={index}
/>
))}
</ul>
);
};
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>
我需要实现一个长列表,长列表中的每一项在onClick的时候都会触发一个新的函数,因为这个函数在每次渲染的时候都是不变的,所以想用useCallback优化一下,这个返回了function Fn需要传参,onClick中是否应该使用bind传参?
const func = useCallback((num) => setIndex(num), [])
// myComponent
<TableItem onClick = { func.bind(null, index) } />
这是我的第一个问题,如果有不对的地方请多多包涵,谢谢
你需要在useCallback中设置第二个参数,这将防止多次渲染。
也就是说,如果你想在组件启动时设置它,你可以设置
useCallback((num => setIndex(num)), [])
注意[],表示只在开始渲染,如果想在任何变量变化时更新,可以设置[variablename, ...]
另外,我觉得你不需要func.bind,你可以只设置
<Component onClick={func}/>
编辑:我误解了这个问题。
如果你想在 onClick 中发送一个参数,你可以这样设置
const func = useCallback((num => setIndex(num)), [])
<Component onClick={()=>func(yourParam)}/>
通过这种方式,您的 onClick 将始终使用该功能,但它允许您可以在任何地方设置的参数
如果将回调传递给多个组件,则可以按以下方式使用 useCallback:
//make Counter a pure component (only re renders if something changed)
const Counter = React.memo(function Counter({
counter,
up,
index,
}) {
// ok to do onClick={new=>'function'} because we do not pass
// onClick to sub components unless counter changes
console.log('rendering index:', index);
return (
<button onClick={() => up(index)}>{counter}</button>
);
});
const App = () => {
//fixed amount of items that does not re order so can use index
// in key, do not use index as key when you don't have fixed
// amount of items or re order the list.
const [counters, setCounters] = React.useState([0, 0]);
const up = React.useCallback(
(index) =>
//pass callback to setCounters so counters is not
// a dependency of useCallback
setCounters((counters) =>
counters.map((counter, i) =>
i === index ? counter + 1 : counter
)
),
[]//empty dependency, only created when App mounts
);
return (
<ul>
{counters.map((counter, index) => (
<Counter
up={up}
counter={counter}
key={index}
index={index}
/>
))}
</ul>
);
};
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>