I need to implement a long list, each item in the long list will trigger a new function when onClick, because this function is unchanged every time it is rendered, so I want to use useCallback to optimize it, this returned function Fn needs to pass in parameters, so should I use bind to pass parameters in onClick?
const func = useCallback((num) => setIndex(num), [])
// myComponent
<TableItem onClick = { func.bind(null, index) } />
This is my first question, please forgive me if something is wrong,Thanks.
If you pass a callback to multiple components then you can use useCallback in the following way:
//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>