T
TanStack16mo ago
conscious-sapphire

Connect parts of table state to redux state

Hi, I want to connect e.g. the columnVisibiliyState to my redux state. The "problem" is the onChange functions, that are typed as OnChangeFn<VisibilityState>. I understand that this is basically the same as the useState's setState function. But i cannot figure out how to replicate this function when using a redux store. Currently I have it like this, but I do not really like the solution much:
// column visibility
const columnVisibilityModel = useAppSelector((state) => state.annotatedSegments.columnVisibilityModel);
const dispatch = useAppDispatch();
const [cvModel, setCvModel] = useState<MRT_VisibilityState>(columnVisibilityModel);
useEffect(() => {
dispatch(AnnotatedSegmentsActions.onColumnVisibilityChange(cvModel));
}, [cvModel, dispatch]);

return (
<MyTable ...
columnVisibilityModel={columnVisibilityModel}
onColumnVisibilityChange={setCvModel}
/>
// column visibility
const columnVisibilityModel = useAppSelector((state) => state.annotatedSegments.columnVisibilityModel);
const dispatch = useAppDispatch();
const [cvModel, setCvModel] = useState<MRT_VisibilityState>(columnVisibilityModel);
useEffect(() => {
dispatch(AnnotatedSegmentsActions.onColumnVisibilityChange(cvModel));
}, [cvModel, dispatch]);

return (
<MyTable ...
columnVisibilityModel={columnVisibilityModel}
onColumnVisibilityChange={setCvModel}
/>
Please tell me how to correctly connect the table state to redux state. Thank you!
4 Replies
conscious-sapphire
conscious-sapphireOP16mo ago
thanks for your answer. I already know about the type of the updater. However, I still have no Idea how to adopt this to work with redux state management... the dispatch operations from redux, in contrast to use state setState methods, do not support callback functions. This is the main issue i am facing
probable-pink
probable-pink16mo ago
You can't just call your redux state setter/dispatcher with the new value?
conscious-sapphire
conscious-sapphireOP16mo ago
i think you are right, I had something wrong in my mind at first. So i created this hook // useReduxConntector.ts
export function useReduxConnector<T>(
reduxStateSelectorFn: (state: RootState) => T,
reduxAction: ActionCreatorWithPayload<T>,
): [T, React.Dispatch<React.SetStateAction<T>>] {
const reduxState = useAppSelector(reduxStateSelectorFn);
const [state, setState] = useState<T>(reduxState);
const dispatch = useAppDispatch();

const onStateChange = useCallback(
(updater: MRT_Updater<T>) => {
setState((oldState) => {
const newState = updater instanceof Function ? updater(oldState) : updater;
dispatch(reduxAction(newState));
return newState;
});
},
[dispatch, reduxAction],
);

// listen to changes
useEffect(() => {
setState(reduxState);
}, [reduxState]);

return [state, onStateChange];
}
export function useReduxConnector<T>(
reduxStateSelectorFn: (state: RootState) => T,
reduxAction: ActionCreatorWithPayload<T>,
): [T, React.Dispatch<React.SetStateAction<T>>] {
const reduxState = useAppSelector(reduxStateSelectorFn);
const [state, setState] = useState<T>(reduxState);
const dispatch = useAppDispatch();

const onStateChange = useCallback(
(updater: MRT_Updater<T>) => {
setState((oldState) => {
const newState = updater instanceof Function ? updater(oldState) : updater;
dispatch(reduxAction(newState));
return newState;
});
},
[dispatch, reduxAction],
);

// listen to changes
useEffect(() => {
setState(reduxState);
}, [reduxState]);

return [state, onStateChange];
}
it takes a redux selector function (to select the relevant state variable from my global state) and a respective redux action that can be used to update the selected global state variable I init the useState hook with the state i select from the local state (so on init the local state and global state are in sync). then, I create a onStateChange function that modifies the setState function to always also call the global state update function (dispatching the provided redux action). This is basically syntax 1 of your linked documentation i return local state and onStateChange function Now i can use it like this in my tables:
// table state
const [rowSelectionModel, setRowSelectionModel] = useReduxConnector(
(state) => state.annotatedSegments.rowSelectionModel,
AnnotatedSegmentsActions.onSelectionModelChange,
);

// table
const table = useMaterialReactTable<AnnotationTableRow>({
...
state: {
rowSelection: rowSelectionModel,
},
onRowSelectionChange: setRowSelectionModel,
...
});
// table state
const [rowSelectionModel, setRowSelectionModel] = useReduxConnector(
(state) => state.annotatedSegments.rowSelectionModel,
AnnotatedSegmentsActions.onSelectionModelChange,
);

// table
const table = useMaterialReactTable<AnnotationTableRow>({
...
state: {
rowSelection: rowSelectionModel,
},
onRowSelectionChange: setRowSelectionModel,
...
});
Could you give me feedback on this solution (performance issues)? thank you so much on responding btw!

Did you find this page helpful?