I am currently working on refactoring a project which wraps around the MUI DataGrid component to use the API object.
To this end, I am trying to implement my own API object implementation in order to expose methods for interacting with a component. However, I am unable to get it to work correctly as a TypeError gets thrown every time:
I am attempting to implement it in the same way as MUI does by taking a MutableRefObject
as a prop, then creating an internal ref inside the component using useRef
, and assigning the handle of the internal ref to the prop ref using useImperativeHandle
:
Creating internal API ref:
const useFilterBuilderApiInitialization = (inputApiRef: React.MutableRefObject<Api> | undefined) => {
const apiRef = useRef() as React.MutableRefObject<Api>;
if (apiRef.current === undefined) {
apiRef.current = {};
}
useImperativeHandle(inputApiRef, () => apiRef.current, [apiRef]);
return apiRef;
}
I am then calling the above hook and assigning the properties of the API ref object inside the component as necessary.
Passing ref into component:
const apiRef = useRef({}) as React.MutableRefObject<Api>;
...
return <Component apiRef={apiRef} />
For further reference, the full source code can be found on GitHub, though it is a bit of a mess at the moment so it probably won't be very useful. The relevant files are FilterRoot.tsx and ODataGridBase.tsx.
It seems to be the useImperativeHandle
call that causes this error specifically - removing it gets rid of the error, but that defeats the purpose because the ref then cannot be accessed outside of the component. Removing the assignment to apiRef.current
or the subsequent assignments to properties of the ref object does not fix the issue.
I'm confused as to why this is happening since I'm doing the exact same thing as the DataGrid does internally as far as I can tell. I guess the error would suggest that the ref is not actually a MutableRefObject
, but is a regular RefObject
?
If anyone knows where I'm going wrong, any help would be much appreciated. I've come across several threads with somewhat similar issues, but none of the suggested solutions have worked. I suppose it would be simpler to just use the ref passed in as a prop directly and avoid useImperativeHandle
, but then this would require passing in a ref even if it won't be used.