I have a component with a save button
<Button onClick={() => requestSaveAsync()}>Save</Button>
I also need to be able to call requestSaveAsync from the top level of the app, so I added a useImperativeHandle hook inside a custom hook called useEditRow
interface Props {
ref: MutableRefObject<{
addItem: () => void
}>
}
const useEditRow = (props: Props) => {
useImperativeHandle(props.ref, () => ({
addItem: () => requestSaveAsync()
})
}
The useEditRow hook is inside of an OrderItemTable component
const OrderItemTable = forwardRef(function OrderItemTable(props: Props, ref: MutableRefObject<any>) {
const editRow = useEditRow({
ref: ref
})
})
The requestSaveAsync method uses useMutation from react-query
useMutation(mutateFn, {
onSuccess: () => dispatch({type: 'clear', name: 'row'})
})
Clear row sets the state to initial state. If requestSaveAsync is called by clicking the button, the row is cleared. If I call it through the parent component, the onSuccess function is called, but the dispatch doesn't do anything. If I put a breakpoint on the dispatch function, I see the following code about to called from 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 () {}];
},
At first I thought that maybe useImperativeHandle was using stale state, so I tried returning {...initialState} instead of initialState. This didn't seem to help. I tried adding the dependencies array suggested by react-hooks/exhaustive-dep. That didn't help. Does anyone know why when dispatch is called from useImperativeHandle, the state doesn't update?
Here is a codesandbox with some of the basic ideas that were shown abo.