Можно ли вызвать useCallback внутри другого обратного вызова
В компоненте A:
const getOnClick = useCallback(
(rec: GenericRec): (() => void) => () => {
setSelectedRecord(rec);
},
[],
);
в компоненте B, дочернем по отношению к A:
const openRecord = useCallback(
(row: Row<Record>) => () => {
getOnClick({ id: row.original.id, name: row.original.name });
},
[getOnClick],
);
getOnClick
не называется
1 ответ
У вас есть дополнительный уровень функций в обоих ваших useCallback
звонки. В отличие от useMemo
, useCallback
непосредственно принимает обратный вызов, который он должен запоминать, а не функцию, которая создает обратный вызов.
Так:
const getOnClick = useCallback(
(rec: GenericRec): (() => void) => {
// ^−−−− no () => here
console.log("getOnClick");
setSelectedRecord(rec);
},
[],
);
const openRecord = useCallback(
(row: Row<Record>) =>
// ^−−−− no () => here
getOnClick({ id: row.original.id, name: row.original.name })
,
[getOnClick],
);
Живой пример (с закомментированными аннотациями типа TypeScript):
const { useState, useCallback } = React;
function Example() {
const [selectedRecord, setSelectedRecord] = useState(null);
const getOnClick = useCallback(
(rec/*: GenericRec*/)/*: (() => void)*/ => {
console.log("getOnClick");
setSelectedRecord(rec);
},
[]/*,*/
);
const openRecord = useCallback(
(row/*: Row<Record>*/) =>
// ^−−−− no () => here
getOnClick({ id: row.original.id, name: row.original.name })
,
[getOnClick]/*,*/
);
const addRecord =() => {
console.log("addRecord");
openRecord({
original: {
id: 1,
name: "The record"
}
});
};
return (
<div>
<input type="button" value="Click Me" onClick={addRecord} disabled={!!selectedRecord} />
{selectedRecord && <span>Selected record: "{selectedRecord.name}" ({selectedRecord.id})</span>}
{!selectedRecord && <em>No record selected</em>}
</div>
);
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>