如何正确使用"next-redux-wrapper"与"Next.js"、"Redux-ToolKit"和打字稿?



我在Next.js应用程序中使用RTK(redux工具包(。我正试图在";getInitialProps";。在搜索时,我发现了一个名为";下一个冗余包装器";这暴露了";存储";内部";getInitialProps";,但我正在努力想办法让它在我的项目中发挥作用。

这是一个项目的基本样本,我目前使用的是带有2个减速器的Typescript。一个reducer正在使用AsyncThunk从API获取数据。我已经安装了";下一个冗余包装器";但我不知道如何围绕实现它,以便所有页面都可以访问";存储";内部";getInitialProps";。该文件包中的Docs有一个例子,但相当令人困惑。

这是我的店铺的样子。。。

import { Action, configureStore, ThunkAction } from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';
import { counterReducer } from '../features/counter';
import { kanyeReducer } from '../features/kanye';
export const store = configureStore({
reducer: {
counter: counterReducer,
kanyeQuote: kanyeReducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;

正如你所看到的,我导入了next-redux-wrapper,但它已经用完了。

以下是我的"_app.tsx";看起来。。。

import { Provider } from 'react-redux';
import type { AppProps } from 'next/app';
import { store } from '../app/store';
function MyApp({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
);
}
export default MyApp;

我需要能够发送";getKanyeQuote"动作在";getInitialProps"在此页面上。。。

import React from 'react';
import { useAppDispatch, useAppSelector } from '../app/hooks';
import { getKanyeQuote } from '../features/kanye';
const kanye: React.FC = () => {
const dispatch = useAppDispatch();
const { data, pending, error } = useAppSelector((state) => state.kanyeQuote);
return (
<div>
<h2>Generate random Kanye West quote</h2>
{pending && <p>Loading...</p>}
{data && <p>{data.quote}</p>}
{error && <p>Oops, something went wrong</p>}
<button onClick={() => dispatch(getKanyeQuote())} disabled={pending}>
Generate Kanye Quote
</button>
</div>
);
};
export default kanye;

这里有一个完整样本的链接。https://stackblitz.com/edit/github-bizsur-zkcmca?file=src%2Ffeatures%2Fcounter%2Freducer.ts

非常感谢您的帮助。

工作演示

首先,配置包装器:

import {
Action,
AnyAction,
combineReducers,
configureStore,
ThunkAction,
} from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';
import { counterReducer } from '../features/counter';
import { kanyeReducer } from '../features/kanye';
const combinedReducer = combineReducers({
counter: counterReducer,
kanyeQuote: kanyeReducer,
});
const reducer = (state: ReturnType<typeof combinedReducer>, action: AnyAction) => {
if (action.type === HYDRATE) {
const nextState = {
...state, // use previous state
...action.payload, // apply delta from hydration
};
return nextState;
} else {
return combinedReducer(state, action);
}
};
export const makeStore = () =>
configureStore({
reducer,
});
type Store = ReturnType<typeof makeStore>;
export type AppDispatch = Store['dispatch'];
export type RootState = ReturnType<Store['getState']>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;
export const wrapper = createWrapper(makeStore, { debug: true });

在这里,新的reducer功能合并了新创建的服务器存储和客户端存储:

  • 包装器使用makeStore函数创建一个新的服务器端冗余存储
  • 包装器分派CCD_ 3动作。其有效负载是新创建的服务器存储
  • reducer将服务器存储区和客户端存储区合并

我们只是用服务器状态替换客户端状态,但如果存储变得复杂,可能需要进一步协调。

包装您的_app.tsx

无需提供Provider和存储,因为wrapper会相应地进行:

import type { AppProps } from 'next/app';
import { wrapper } from '../app/store';
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
export default wrapper.withRedux(MyApp);

然后您可以在页面中发送thunk操作:

import { NextPage } from 'next/types';
import React from 'react';
import { useAppDispatch, useAppSelector } from '../app/hooks';
import { getKanyeQuote } from '../features/kanye';
import { wrapper } from '../app/store';
const kanye: NextPage = () => {
const dispatch = useAppDispatch();
const { data, pending, error } = useAppSelector((state) => state.kanyeQuote);
return (
<div>
<h2>Generate random Kanye West quote</h2>
{pending && <p>Loading...</p>}
{data && <p>{data.quote}</p>}
{error && <p>Oops, something went wrong</p>}
<button onClick={() => dispatch(getKanyeQuote())} disabled={pending}>
Generate Kanye Quote
</button>
</div>
);
};
kanye.getInitialProps = wrapper.getInitialPageProps(
({ dispatch }) =>
async () => {
await dispatch(getKanyeQuote());
}
);
export default kanye;

遵循next-redux-wrapperrepo的使用指南。在你的存储文件将是

import { Action, configureStore, ThunkAction } from '@reduxjs/toolkit';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';
import { counterReducer } from '../features/counter';
import { kanyeReducer } from '../features/kanye';
const store = configureStore({
reducer: {
counter: counterReducer,
kanyeQuote: kanyeReducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;
const makeStore = () => store;
export const wrapper = createWrapper(makeStore);

和后的_app.js文件更改

import type { AppProps } from 'next/app';
import { wrapper } from '../app/store';
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
export default wrapper.withRedux(MyApp);

然后直接到/kanye页面它应该可以

相关内容

  • 没有找到相关文章

最新更新