Redux 工具包存储在下一个 js 中的页面之间导航时自动重置

我是 Next 的新用户,并且长期以来一直使用 Redux 和 React 我在使用 Redux 和 Next 时遇到了很多麻烦

我已经完成了这个解决方案

store.js

import { configureStore } from '@reduxjs/toolkit';
import reducers from './rootReducer';

export function makeStore() {
  return configureStore({
    reducer: reducers,
  });
}

const store = makeStore();

export default store;

rootReducer.js

import { combineReducers } from '@reduxjs/toolkit';
import tes from './test/tes';

const reducers = combineReducers({
  test: tes,
});

export default reducers;

_app.js

import React from 'react';
import { Provider } from 'react-redux';
import store from '../redux/store';
import { createWrapper } from 'next-redux-wrapper';

const MyApp = ({ Component, ...rest }) => {
  return (
    <Provider store={store}>
      <Component {...rest} />
    </Provider>
  );
};
const makestore = () => store;
const wrapper = createWrapper(makestore);

export default wrapper.withRedux(MyApp);

但是我发现,任何使用了 useDispatch 的任何页面里面,在获取数据后,搜索引擎都无法识别页面的内容

import React, { useEffect } from 'react';
import { Test } from '../../redux/test/tes';
import { useDispatch, useSelector } from 'react-redux';
import Link from 'next/link';

function TestPage() {
  const dispatch = useDispatch();
  const { data } = useSelector((state) => state.test);
  useEffect(() => {
    dispatch(Test('hi'));
  }, []);
  return (
    <div>
      <Link href="/">
        <a>home</a>
      </Link>{' '}
      {data.map((name) => (
        <h1>{name.title}</h1>
      ))}
    </div>
  );
}

export default TestPage;

必须使用下一个预渲染方法之一

我想知道这是否正常下一个

或者有更好的方法吗?


#1 更新

现在将数据提取移动到 getStaticProps

TestPage.js

import React from 'react';
import { Test } from '../../redux/test/tes';
import {  useSelector } from 'react-redux';
import Link from 'next/link';
import { wrapper } from '../../redux/store';

function TestPage({ pageProps }) {
  const { data } = useSelector((state) => state.test);
  console.log(data);

  return (
    <div>
      <Link href="/">
        <a>home</a>
      </Link>{' '}
      {data && data.map((name) => (
        <h1>{name.name}</h1>
      ))}
    </div>
  );
}
export const getStaticProps = wrapper.getStaticProps(
  (store) => async (context) => {
    const loading = store.getState().test.loading;
    if (loading === 'idle') {
      await store.dispatch(Test('hi'));

    }

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

export default TestPage;

现在的问题是商店没有更新 useSelector return []

虽然来自 getStaticProps 的 console.log (data) 数据存在 __NEXT_REDUX_WRAPPER_HYDRATE__ 我被卡住了


#2 更新

到达这里真的很难,在那之后,使用 Next js 获取 Redux 仍然存在问题

现在一切正常,直到导航到具有 getStaticPropsgetServerProps 的任何页面

状态自动重置

store.js

import reducers from './rootReducer';
import { configureStore } from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';

const reducer = (state, action) => {
  if (action.type === HYDRATE) {
    let nextState = {
      ...state,
      ...action.payload,
    };
    return nextState;
  } else {
    return reducers(state, action);
  }
};

const isDev = process.env.NODE_ENV === 'development';

const makeStore = (context) => {
  let middleware = [];

  const store = configureStore({
    reducer,
    middleware: (getDefaultMiddleware) =>
      getDefaultMiddleware().concat(middleware),
    devTools: isDev,
    preloadedState: undefined,
  });

  return store;
};

export const wrapper = createWrapper(makeStore, { debug: isDev });
stack overflow Redux toolkit store reset automatically in navigating between pages in next js
原文答案
author avatar

接受的答案

最后,这种方式只管用。甚至服务器和客户端状态分离也不起作用。

我用过这个 jsondiffpatch

rootReducer.js

const rootReducer = createReducer(
  combinedReducers(undefined, { type: '' }),
  (builder) => {
    builder
      .addCase(HYDRATE, (state, action) => {
        const stateDiff = diff(state, action.payload);
        const isdiff = stateDiff?.test?.data?.[0];
        const isdiff1 =
          stateDiff?.test1?.data?.[0] 
        return {
          ...state,
          ...action.payload,

          test: isdiff ? action.payload.test : state.test,
          test1: isdiff1 ? action.payload.test1 : state.test1,
        };
      })
      .addDefaultCase(combinedReducers);
  }
);

这里唯一的问题是你必须测试状态内每一部分的每一个变化

更新

因为全局水合物还原剂可能会过度杀伤,所以这里有一个处理每个切片中水合的示例:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { diff } from 'jsondiffpatch';
import { HYDRATE } from 'next-redux-wrapper';

const initialState = {
  data: [],
};
export const TestFetch = createAsyncThunk(
  'TestFetch',
  async (data, { rejectWithValue, dispatch }) => {
    try {
      const response = await fetch(
        'https://jsonplaceholder.typicode.com/users'
      );
      const d = await response.json();
      return d;
    } catch (error) {
      return rejectWithValue(error.response.data.error);
    }
  }
);

const test = createSlice({
  name: 'test',
  initialState,
  reducers: {
    update: {
      reducer: (state, { payload }) => {
        return { ...state, data: payload };
      },
    },
  },
  extraReducers: {
    [HYDRATE]: (state, action) => {
      const stateDiff = diff(state, action.payload);
      const isdiff1 = stateDiff?.server?.[0]?.test?.data?.[0];
      // return {
      //   ...state,
      //   data: isdiff1 ? action.payload.server.test.data : state.data,
      // };
      state.data = isdiff1 ? action.payload.server.test.data : state.data;
    },
    [TestFetch.fulfilled]: (state, action) => {
      state.data = action.payload;
    },
  },
});

export const { update } = test.actions;
export default test.reducer;

答案:

作者头像

1.) 将 Redux 与 Nextjs 一起使用会消除 SEO 优势吗?

不,将 Redux 与 NextJs 一起使用不会妨碍 SEO 优势。 Redux 与 NextJS 配合得很好。

问题在于您对数据获取的实现。 NextJS 看不到获取的内容,因为您需要在 getInitialPropsgetServerSidePropsgetStaticProps 中获取它,具体取决于您希望应用程序工作的方式。

请参阅 NextJS 的 Data Fetching documentation

请注意, getServerSidePropsgetStaticProps 是处理数据获取的推荐方法。

如果你选择 getStaticProps ,你将需要 getStaticPaths 。检查此答案以查看用例和 difference between the getStaticPaths and getStaticProps ,因为它可能会造成混淆。

TLDR;不要将数据获取放在 useEffect 挂钩中,而是将其移动到 getServerSidePropsgetStaticProps 函数中。