简体   繁体   English

如何正确使用带有“Next.js”、“Redux-ToolKit”和 Typescript 的“next-redux-wrapper”?

[英]How to use "next-redux-wrapper" with "Next.js", "Redux-ToolKit" and Typescript properly?

I'm using RTK (redux-toolkit) inside a Next.js App.我在 Next.js 应用程序中使用 RTK(redux-toolkit)。 And I'm trying to dispatch an AsyncThunk Action inside "getInitialProps".我正在尝试在“getInitialProps”中调度一个 AsyncThunk Action。 When searching I found a package called "next-redux-wrapper" that exposes the "store" inside "getInitialProps", but I'm struggling to figure out how to make it work with my project.搜索时,我发现了一个名为“next-redux-wrapper”的 package,它暴露了“getInitialProps”中的“商店”,但我正在努力弄清楚如何让它与我的项目一起使用。

Here's a barebone sample of the project where I'm using Typescript with 2 reducers at the moment.这是该项目的准系统示例,我目前正在使用带有 2 个减速器的 Typescript。 One reducer is using AsyncThunk to get data from an API.一个 reducer 使用 AsyncThunk 从 API 获取数据。 I already installed "next-redux-wrapper" but I don't know how to implement it around the so that all pages get access to the "store" inside "getInitialProps".我已经安装了“next-redux-wrapper”,但我不知道如何实现它,以便所有页面都可以访问“getInitialProps”中的“store”。 The Docs of that package has an example but rather a confusing one.该 package 的文档有一个示例,但令人困惑。

Here's how my store.ts looks like...这是我的 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>
>;

As you can see I imported next-redux-wrapper , but that's abuout it.如您所见,我导入next-redux-wrapper ,仅此而已。

And here's how my "_app.tsx" looks like...这就是我的“_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;

I need to be able to dispatch the "getKanyeQuote" action in "getInitialProps" on this page...我需要能够在此页面的“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;

And here's a link to a full sample.这是完整示例的链接。 https://stackblitz.com/edit/github-bizsur-zkcmca?file=src%2Ffeatures%2Fcounter%2Freducer.ts https://stackblitz.com/edit/github-bizsur-zkcmca?file=src%2Ffeatures%2Fcounter%2Freducer.ts

Any help is highly appreciated.非常感谢任何帮助。

Following the Usage guide on next-redux-wrapper repo.遵循next-redux-wrapper repo 上的使用指南 Within you store file will be在您的存储文件中将是

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);

and _app.js file change following和 _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);

Then direct to /kanye page It should works然后直接到/kanye页面它应该可以工作

WORKING DEMO工作演示

https://stackblitz.com/edit/github-bizsur-azd1ro?file=src%2Fpages%2Fkanye.tsx https://stackblitz.com/edit/github-bizsur-azd1ro?file=src%2Fpages%2Fkanye.tsx

First, configure wrapper:首先,配置包装器:

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 });

Here the new reducer function merges newly created server store and client store:这里新的 reducer function 合并了新创建的服务器存储和客户端存储:

  • wrapper creates a new server side redux store with makeStore function wrapper 使用makeStore function 创建一个新的服务器端 redux 存储
  • wrapper dispatches HYDRATE action. wrapper 调度HYDRATE动作。 Its payload is newly created server store它的有效载荷是新创建的服务器存储
  • reducer merges server store with client store. reducer 将服务器存储与客户端存储合并。

We're just replacing client state with server state but further reconcilation might be required if the store grows complicated.我们只是用服务器 state 替换客户端 state,但如果商店变得复杂,可能需要进一步协调。

wrap your _app.tsx包装你的 _app.tsx

No need to provide Provider and store because wrapper will do it accordingly:无需提供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);

And then you can dispatch thunk action in your page:然后您可以在您的页面中发送 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.

相关问题 Next.js:getServerSideProps 无法使用 Next.js 和 Next-redux-wrapper 以及 TypeScript - Next.js: getServerSideProps not working using Next.js with Next-redux-wrapper with TypeScript Redux 工具包 typescript 类型问题与 next js 和 next-redux-wrapper - Redux toolkit typescript type issue with next js and next-redux-wrapper 如何使用 typescript、next-redux-wrapper、getServerSideProps? - how to use typescript, next-redux-wrapper, getServerSideProps? Next.js:使用带有 TypeScript 的 next-redux-wrapper 在 getServerSideProps 中调用 Thunks? - Next.js: Calling Thunks in getServerSideProps with next-redux-wrapper with TypeScript? nextjs 中 getServerSideProps 中的 next-redux-wrapper - next-redux-wrapper in getServerSideProps in nextjs Redux Toolkit 和 typescript 中的 Next Redux Wrapper 类型错误? - Type error with Redux Toolkit and Next Redux Wrapper in typescript? 使用 redux-persist 和 next-redux-wrapper (Typescript) 不更新存储 - storage is not being update using redux-persist with next-redux-wrapper (Typescript) 如何在 redux-toolkit 中正确使用带有元类型的 PayloadAction? - How to properly use PayloadAction with meta type in redux-toolkit? 如何修复 redux-toolkit 中的 typescript 错误? - How to fix typescript error in redux-toolkit? Next.Js Redux Wrapper w/Typescript - 实现错误,存储不存在为类型 - Next.Js Redux Wrapper w/ Typescript - Implementation error, store does not exist as type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM