简体   繁体   中英

how to write onClick (with arguments) optimized by useCallback in React?

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>

You need to set the second param in useCallback, this will prevent multiple renders.

ie, if you want to set it just in when the component starts you can set

useCallback((num => setIndex(num)), [])

Note that [], it means it will only render at the beginning, if you want to update it when any variable changes, you can set [variablename, ...]

Also, I think you don't need the func.bind, you can set only

<Component onClick={func}/>

Edit: I misunderstood this question.

If you want to send a param in the onClick you can set it like this

const func = useCallback((num => setIndex(num)), [])
<Component onClick={()=>func(yourParam)}/>

With this way your onClick will always use the function, but it allows a param that you can set anywhere

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