Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hydration Never Occurs When Using getStaticProps and fallback:true #570

Open
gabriel-earle opened this issue Aug 22, 2024 · 0 comments
Open
Labels

Comments

@gabriel-earle
Copy link

Describe the bug

In my implementation, the HYDRATE action is never dispatched when using getStaticProps and fallback: true on an initial page load. I've added detailed logs to my HYDRATE action handler, and I've found that the logs come out in the node console that is running the local next server and the resulting state looks perfect. However, these logs never appear in the browser console. Additionally, using Redux Devtools, the HYDRATE action type is never observed.

This bug only occurs on initial page load. If I start on a different page, then navigate to the getStaticProps/fallback: true page through a nextjs component, then everything works perfectly, and I observe the HYDRATE action type in Redux Devtools. Also, If I switch the loading behavior to fallback: "blocking" in getStaticPaths, the HYDRATE action is dispatched as expected, and everything works perfectly, however, I need support for fallback: true for my use case. Even more strange, if I use fallback: true, load the page, then subsequently save my code to trigger a hot reload, then the HYDRATE action is dispatched.

I am using redux toolkit, specifically using createSlice and configureStore to setup redux, but not using any of the API features.

My code

I've removed variable names/repetition for brevity/privacy, but all of the information is here.

My store definition:

const makeStore = () => {
  return configureStore({
    reducer: {
      // 15 slices of the following pattern:
      [X.reducerPath]: X.reducer
    },
  });
};
export const wrapper = createWrapper(makeStore);

my _app.js file (irrelevant parts removed). As you can see, it passes the store returned from wrapper.useWrappedStore to the Provider, and it also places the store in the api class, which I know is an unconventional behavior, however when removing this line, it does not fix the bug.

export default function App({ Component, ...rest }) {
  const { store, props } = wrapper.useWrappedStore(rest);
  api.store = store;

  useEffect(() => {
    // init api
    api.init();
  }, []);

  return (
      <main className={font.className}>
        <Provider store={store}>
          <Component {...props.pageProps} />
        </Provider/>
      </main>
  )
}

my getStaticProps usage:

export const getStaticProps = wrapper.getStaticProps(
  (store) =>
    async ({ params }) => {
      try {
        if (params.id) {
          const response = await axios.get(`/endpoint/${params.id}`);
          if (response.data.comments) {
            store.dispatch({
              type: "comments/storeMany",
              payload: response.data.comments,
            });
          }
        }
      } catch (err) {}

      return { props: {}, revalidate: 600 };
    }
);

my HYDRATE action hander. I'm doing it in the extraReducers section of redux toolkit's createSlice for each slice to keep the code separate. This is definitely working, because when logging through the local next server, the correct new state is returned for every slice. And, when switching to fallback: "blocking" for testing, the hydration result is perfect. So this shouldn't be the issue.

extraReducers: (builder) => {
      builder.addCase(HYDRATE, (state, action) => {
        const newEntries = action.payload[name].cache.filter(Boolean);
        if (!newEntries.length) return state;
        return { ...state, cache: mapConcat(state.cache, newEntries) };
      });
    },

What can I do to make sure the HYDRATE action is dispatched on the client after first navigations to a page using fallback: true and getStaticProps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant