在 Next 14 的 appRouter 模式中接入 React-Redux

在 Next 14 的 appRouter 模式中接入 React-Redux

说明

Next.js 版本升级到 14 后,相比 13 版本是一个改动很大的大版本升级,很多概念或者使用方式 13 版本都有较大的区别,因此这里记录一些学习 14 版本的 Next.js 的心得体会或者问题。因为我这边构建项目选择的是 Next.js 新的路由模式 App Router,因此该文档是基于 App Router 路由模式的。

安装依赖

根据 react-redux 官方文档 的说明,使用如下面命令安装依赖:

pnpm add @reduxjs/toolkit react-redux

创建 store 模块

我们以创建一个 counterSlice 举例:
在项目根目录(或者 app 目录,或者其他目录),创建 store 目录,以及 react-redux 的主文件 store.ts,然后创建 /storemodules/counterSlice.ts,并写入如下代码:

//counterSlice.jsx

"use client"; //this is a client side component

import { createSlice } from "@reduxjs/toolkit";
import { RootState } from "../store";

const initialState = {
  value: 0,
};

export const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;

export const selectCounter = (state: RootState) => state.counter.value;

**注意:**这里需要注意,在 next 中,redux 需要作为客户端渲染的模块,因此 store 模块的文件头部都需要加上使用客户端渲染的注解 "use client";
然后在 store.ts 里面写入如下代码:

//store.jsx

"use client";
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import counterReducer from "./modules/counterSlice";
import { Provider } from "react-redux";

const rootReducer = combineReducers({
  counter: counterReducer,
  //add all your reducers here
});

export const store = configureStore({
  reducer: rootReducer,
});

export function ReduxProvider({ children }) {
  return <Provider store={store}>{children}</Provider>;
}

export type RootState = ReturnType<typeof store.getState>;

export type AppDispatch = typeof store.dispatch;

ReduxProvider作为组件抛出去。

使用定义好的 store 模块

注册 Provider

我们可以在全局 layout 里面注册 Provider, 这样能保证我们的所有的客户端组件都能使用 Redux:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import ThemeRegistry from "@/app/components/themeRegistry/ThemeRegistry";
import HeaderBar from "@/app/components/layout/HeaderBar";
import { ReduxProvider } from "@/app/store/store";
import { useEffect } from "react";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App11",
  description: "Generated by create next app",
};

function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ReduxProvider>
          <ThemeRegistry>
            <HeaderBar />
            {children}
          </ThemeRegistry>
        </ReduxProvider>
      </body>
    </html>
  );
}

// export default wrapper.withRedux(RootLayout);
export default RootLayout;

组件中使用 redux

之前已经说了,reduxnext.js 中只能是作为客户端渲染模块使用,所以我们不能再任何的 page.tsx 路由页面组件中使用(除非这个路由页面有客户端渲染组件注解use client;,然而这种情况可能并不多见。),因此对于需要使用 redux 的地方,我们需要这块儿逻辑封装成客户端渲染的组件,比如:

"use client";
import {
  decrement,
  increment,
  selectCounter,
} from "@/app/store/modules/counterSlice";
import { AppDispatch } from "@/app/store/store";
import { Box, Button, Typography } from "@mui/material";
import { useDispatch, useSelector } from "react-redux";

export default function CounterControl() {
  const counter = useSelector(selectCounter);
  const dispatch = useDispatch<AppDispatch>();

  const handleChangeCounter = (type: "ADD" | "MINUS") => {
    dispatch(type === "ADD" ? increment() : decrement());
  };

  return (
    <Box>
      <Typography variant="h1">{counter}</Typography>
      <Box>
        <Button variant="outlined" onClick={() => handleChangeCounter("ADD")}>
          ADD
        </Button>
        <Button
          variant="outlined"
          onClick={() => handleChangeCounter("MINUS")}
          sx={{ ml: 2 }}
        >
          MINUS
        </Button>
      </Box>
    </Box>
  );
}

这样子我们就可以在任意组件(包括路由组件 page.tsx)里面使用封装的这个 CounterControl 组件了:

import { Metadata } from "next";
import { Button } from "@mui/material";
import NavigateButton from "@/app/components/tools/NavigateButton";
import CounterControl from "../components/counter/CounterControl";

export const metadata: Metadata = {
  title: "Users page",
  description: "Generated by create next app",
};

export default function UsersPage() {
  return (
    <div>
      <CounterControl />
      <Button sx={{ mx: 1 }} variant="contained">
        Hellow Mui
      </Button>
      <NavigateButton destination="/" variant="contained" sx={{ mx: 2 }}>
        back
      </NavigateButton>
      <h2>This is the User Index page</h2>
    </div>
  );
}

以上就完成了在 Next.js 14App Router 路由模式中接入 react-redux 的全过程。

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值