[英]Next.js: getServerSideProps not working using Next.js with Next-redux-wrapper with TypeScript
[英]How to use "next-redux-wrapper" with "Next.js", "Redux-ToolKit" and Typescript properly?
我在 Next.js 應用程序中使用 RTK(redux-toolkit)。 我正在嘗試在“getInitialProps”中調度一個 AsyncThunk Action。 搜索時,我發現了一個名為“next-redux-wrapper”的 package,它暴露了“getInitialProps”中的“商店”,但我正在努力弄清楚如何讓它與我的項目一起使用。
這是該項目的准系統示例,我目前正在使用帶有 2 個減速器的 Typescript。 一個 reducer 使用 AsyncThunk 從 API 獲取數據。 我已經安裝了“next-redux-wrapper”,但我不知道如何實現它,以便所有頁面都可以訪問“getInitialProps”中的“store”。 該 package 的文檔有一個示例,但令人困惑。
這是我的 store.ts 的樣子......
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;
我需要能夠在此頁面的“getInitialProps”中發送“getKanyeQuote”操作...
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
非常感謝任何幫助。
遵循next-redux-wrapper
repo 上的使用指南。 在您的存儲文件中將是
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
頁面它應該可以工作
https://stackblitz.com/edit/github-bizsur-azd1ro?file=src%2Fpages%2Fkanye.tsx
首先,配置包裝器:
import {
Action,
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, action) => {
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 function 合並了新創建的服務器存儲和客戶端存儲:
makeStore
function 創建一個新的服務器端 redux 存儲HYDRATE
動作。 它的有效載荷是新創建的服務器存儲我們只是用服務器 state 替換客戶端 state,但如果商店變得復雜,可能需要進一步協調。
包裝你的 _app.tsx
無需提供Provider
和 store,因為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.getInitialAppProps(
({ dispatch }) =>
async () => {
await dispatch(getKanyeQuote());
}
);
export default kanye;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.