Простой ответ здесь, вы, вероятно, не должны использовать useCallback
здесь.Смысл useCallback
состоит в том, чтобы передать один и тот же экземпляр функции оптимизированным компонентам (например, PureComponent
или React.memo
ized компонентам), чтобы избежать ненужных повторных отображений.
В этом случае вы не имеете дело с оптимизированными компонентами (или, как я подозреваю, в большинстве случаев), поэтому на самом деле нет причин запоминать обратные вызовы, такие как useCallback
.
Предполагая, что запоминание важно, однако, лучшее решение здесь, вероятно, состоит в том, чтобы использовать одну функцию вместо пяти: вместо уникальной функции для каждой кнопки выполняется закрытие key
, вы можете прикрепить key
к элементу:
<button data-key={key}>{key}</button>
А затем прочитайте ключ из event.target.dataset["key"]
в обработчике одного клика:
const Example = (props) => {
// Single callback, shared by all buttons
const onClick = React.useCallback((e) => {
// Check which button was clicked
const key = e.target.dataset["key"]
console.log("You clicked: ", key);
}, [/* dependencies */]);
return(
<div>
{
_.times(5, (key) => {
return (
<button data-key={key} onClick={onClick}>
{key}
</button>
);
})
}
</div>
);
};
console.log("hello there");
ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id='root'>
</div>
При этом можно запоминать несколько функций в одном хуке.useCallback(fn, deps)
эквивалентно useMemo(() => fn, deps)
, а useMemo
может использоваться для запоминания нескольких функций одновременно:
const clickHandlers = useMemo(() => _.times(5, key =>
() => console.log("You clicked", key)
), [/* dependencies */]);
const Example = (props) => {
const clickHandlers = React.useMemo(() => _.times(5, key =>
() => console.log("You clicked", key)
), [/* dependencies */])
return(
<div>
{
_.times(5, (key) => {
return (
<button onClick={clickHandlers[key]}>
{key}
</button>
);
})
}
</div>
);
};
console.log("hello there");
ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id='root'>
</div>
Возможно, есть случай, когда это полезно, но в этом случае я бы либо оставил его в покое (и не беспокоился об оптимизации), либо использовал бы один обработчикза каждую кнопку.