My problem is that a component doesn't seem to receive the proper redux state (in time?) and therefore doesn't display the sidebar component in this redux state.
The called page looks like this:
const MyLandingPage: NextPage = () => {
const { setLayout } = useSetLayout(); // the Redux dispatch method, see below
...
useEffect(
() => {
setLayout({
sidebar: {
content: <FeedSidebar filters={filters} setFilters={setNewFilters} />
});
},
[...]
);
return <MyComponent ... />
}
This page will be embedded in the side column of my Layout.tsx
:
export const Layout: React.FC = () => {
const sidebar = useSidebarContentSelector(); // the Redux selection method, see below
console.log('sidebar in Layout:', sidebar);
return <SomeOtherComponents>{sidebar?.content}<SomeOtherComponents>;
}
The Redux-related hooks for the sidebar state looks like this:
export const useSidebarContentSelector = () => useSelector((state: RootState) => state.sidebarContent);
export const useSetLayout = () => {
const { setSidebar } = sidebarContentSlice.actions;
const dispatch = useAppDispatch();
return {
setLayout: (commands: { sidebar?: SidebarState) => {
console.log('setting sidebar:', commands.sidebar);
dispatch(setSidebar(commands.sidebar));
}
}
}
The logs reads like:
sidebar in Layout: null
setting sidebar: Object { content: {…} }
sidebar in Layout: null
useSidebarContentSelector
and useSidebarContentDispatch
work on other occasions, I'm rather sure they are alright. But for some reason the sidebar in Layout.tsx
doesn't receive the update and I figure just keeps displaying the state from the SSR.
I'm grateful for any ideas why the updated sidebar isn't received despite being dispatched and the Layout
component rerendering!
Found it. I wasn't using a Redux store singleton, so with every rerender a new store was created. One solution might be to create the store with const store => useMemo(() => configureStore(...), [])
, but for my design it was more straight-forward to go with
const isServerSide = typeof window === 'undefined';
const clientSideReduxStore = configureStore(...);
export const ReduxProvider: React.FC<
Omit<ProviderProps, 'store'> & { preloadedState?: Partial<RootState> }
> = (props) => {
return isServerSide ? Provider({store: configureStore(...)) : clientSideReduxStore
}
Note that the on SSR a new store must be created at any call, so I mustn't return clientSideReduxStore
in case I'm at the server-side.