Tengo un componente con un botón de guardar.
<Button onClick={() => requestSaveAsync()}>Save</Button>También necesito poder llamar a requestSaveAsync desde el nivel superior de la aplicación, así que agregué un enlace useImperativeHandle dentro de un enlace personalizado llamado useEditRow
interface Props { ref: MutableRefObject<{ addItem: () => void }> } const useEditRow = (props: Props) => { useImperativeHandle(props.ref, () => ({ addItem: () => requestSaveAsync() }) }El gancho useEditRow está dentro de un componente OrderItemTable
const OrderItemTable = forwardRef(function OrderItemTable(props: Props, ref: MutableRefObject<any>) { const editRow = useEditRow({ ref: ref }) })El método requestSaveAsync usa useMutation de react-query
useMutation(mutateFn, { onSuccess: () => dispatch({type: 'clear', name: 'row'}) })Borrar fila establece el estado en el estado inicial. Si se llama a requestSaveAsync haciendo clic en el botón, la fila se borra. Si lo llamo a través del componente principal, se llama a la función onSuccess, pero el envío no hace nada. Si coloco un punto de interrupción en la función de envío, veo el siguiente código a punto de ser llamado desde react_devtools_backend.js
useReducer: function (a, b, e) { a = F(); b = null !== a ? a.memoizedState : void 0 !== e ? e(b) : b; z.push({ primitive: "Reducer", stackError: Error(), value: b }); // devtools show the empty function on this line will be executed next return [b, function () {}]; },Al principio pensé que tal vez useImperativeHandle estaba usando un estado obsoleto, así que intenté devolver {...initialState} en lugar de initialState. Esto no pareció ayudar. Intenté agregar la matriz de dependencias sugerida por react-hooks/exhaustive-dep. Eso no ayudó. ¿Alguien sabe por qué cuando se llama a dispatch desde useImperativeHandle, el estado no se actualiza?
Aquí hay una caja de códigos con algunas de las ideas básicas que se mostraron arriba.
Su gancho useImperativeHandle no parece estar usando la referencia React reenviada . En otras palabras, las referencias de React no son accesorios de React regulares a los que pueden acceder los componentes secundarios.
Debe usar React.forwardRef para reenviar correctamente cualquier referencia pasada al componente de la función.
React.forwardRef Referencias de reenvío
No incluyó su componente de función, pero si sigue los ejemplos en los enlaces provistos, es bastante trivial de averiguar.
Ejemplo:
const MyComponentWithSaveButton = (props, ref) => { useImperativeHandle(ref, () => ({ addItem: requestSaveAsync, })); const requestSaveAsync = () => { .... }; ... }; export default React.forwardRef(MyComponentWithSaveButton); Observe aquí que la firma del componente de la función no acepta dos argumentos, el objeto props y la ref React que se está reenviando, y que el useImperativeHandle hace referencia a la ref reenviada.