英文:
How to use Redux Toolkit with Next.js and App-Router?
问题
这是Redux Toolkit在NextJS 13应用程序路由中的使用示例。以下是与Redux Toolkit相关的所有切片和代码。请注意,这里不包括完整的代码,只提供了关键部分的翻译:
-
apiSlice.js
:API切片的定义,用于与后端通信。 -
usersApiSlice.js
:用户API切片的定义,包括登录、注册和注销等功能。 -
authSlice.js
:身份验证切片的定义,包括设置凭据和注销等功能。 -
provider.js
:React Redux提供程序的定义,用于在整个应用程序中提供Redux存储。 -
store.js
:Redux存储的配置,包括authReducer和API切片的中间件。 -
layout.js
:应用程序的布局组件,包括提供Redux存储和头部。 -
login/page.jsx
:登录页面的定义,包括表单处理和与Redux存储的交互。
如果您有关于特定部分的问题或需要更多详细信息,请提出具体问题。
英文:
How to use Redux toolkit in NextJS 13 App router ?
These are all my slices and code related to redux toolkit Is there anything wrong with the code coz I get this error in terminal saying , I think In Nextjs 13 we have to create a seperate provider like I did but I don't know what the error please help me find the error:
apiSlice.js:
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
const baseQuery = fetchBaseQuery({
baseUrl: "http://localhost:8000/",
credentials: "include",
});
export const apiSlice = createApi({
baseQuery,
tagTypes: ["User"],
endpoints: (builder) => ({}),
});
usersApiSlice.js:
import { apiSlice } from "./apiSlice";
const USERS_URL = "http://localhost:8000/api/users";
export const usersApiSlice = apiSlice.injectEndpoints({
endpoints: (builder) => ({
login: builder.mutation({
query: (data) => ({
url: `${USERS_URL}/auth`,
method: "POST",
body: data,
}),
}),
register: builder.mutation({
query: (data) => ({
url: `${USERS_URL}`,
method: "POST",
body: data,
}),
}),
logout: builder.mutation({
query: () => ({
url: `${USERS_URL}/logout`,
method: "POST",
}),
}),
}),
});
export const { useLoginMutation, useLogoutMutation, useRegisterMutation } =
usersApiSlice;
authSlice.js :
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
userInfo: null,
};
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
setCredentials: (state, action) => {
state.userInfo = action.payload;
localStorage.setItem("userInfo", JSON.stringify(action.payload));
},
logout: (state, action) => {
state.userInfo = null;
localStorage.removeItem("userInfo");
},
},
});
export default authSlice.reducer;
export const { setCredentials, logout } = authSlice.actions;
provider.js:
"use client";
import { Provider } from "react-redux";
import { store } from "./store";
export function Providers({ children }) {
return <Provider store={store}>{children}</Provider>;
}
export default Providers;
store.js :
import { configureStore } from "@reduxjs/toolkit";
import authReducer from "./features/auth/authSlice";
import { apiSlice } from "./features/api/apiSlice";
export const store = configureStore({
reducer: {
auth: authReducer,
[apiSlice.reducerPath]: apiSlice.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(apiSlice.middleware),
devTools: true,
});
layout.js:
"use client";
import "./globals.css";
import { Providers } from "./GlobalRedux/provider";
// import { ToastContainer } from "react-toastify";
// import "react-toastify/dist/ReactToastify.css";
import { Inter } from "next/font/google";
import Header from "./components/Header";
import { Provider } from "react-redux";
import { store } from "./GlobalRedux/store";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<Provider store={store}>
<Header />
{children}
</Provider>
</body>
</html>
);
}
login/page.jsx :
"use client";
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useLoginMutation } from "@/app/GlobalRedux/features/api/usersApiSlice";
import { setCredentials } from "@/app/GlobalRedux/features/auth/authSlice";
import { useRouter } from "next/navigation";
// import { toast } from "react-toastify";
import styles from "../loginregister.module.css";
const page = () => {
const router = useRouter();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const dispatch = useDispatch();
const [login, { isLoading, error }] = useLoginMutation();
const { userInfo } = useSelector((state) => state.auth);
useEffect(() => {
if (userInfo) {
router.push("/");
}
}, [router, userInfo]);
const submitHandler = async (e) => {
e.preventDefault();
try {
const res = await login({ email, password });
dispatch(setCredentials({ ...res }));
if (res.data.status === 201) {
router.push("/");
}
} catch (err) {
alert(err?.data?.message || err.error);
// toast.error(err?.data?.message || err.error);
}
};
return (
<div className={styles.form}>
<h1>Login</h1>
<form onSubmit={submitHandler}>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
type="email"
name="email"
placeholder="Email"
/>
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
name="password"
placeholder="Password"
/>
{isLoading && <h2>Loading...</h2>}
<button>Login</button>
</form>
</div>
);
};
export default page;
答案1
得分: 2
Here are the translated parts of the provided code:
In JSX or TSX:
import { Provider } from "react-redux";
import { store } from "./store";
import React from "react";
export default function ReduxProvider({ children }: { children: React.ReactNode }) {
return <Provider store={store}>{children}</Provider>;
};
In your Layout:
import './globals.css';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import ReduxProvider from "@/app/store/ReduxProvider";
const inter = Inter({ subsets: ['latin'] });
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<ReduxProvider>
{children}
</ReduxProvider>
</body>
</html>
);
}
Please note that I've converted the HTML-like tags back to their JSX/TSX equivalents for clarity.
英文:
Create à ReduxProvider in jsx or tsx :
"use client";
import {Provider} from "react-redux"
import {store} from "./store";
import React from "react";
export default function ReduxProvider({children}: { children: React.ReactNode }) {
return <Provider store={store}>{children}</Provider>;
};
And in your Layout :
import './globals.css'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import ReduxProvider from "@/app/store/ReduxProvider";
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
<ReduxProvider>
{children}
</ReduxProvider>
</body>
</html>
)
}
答案2
得分: 1
我通过在进行数据请求的组件中添加'use client'来解决了这个问题。由于Redux只在客户端初始化,因此服务器组件(没有'use client'头部的组件)无法使用RTK。
英文:
I solved this problem by adding 'use client' to the component in which I was making a data request via RTK Query. Since Redux is initialized only on the client, server components (components without the 'use client' header) cannot use RTK.
答案3
得分: 0
你已经创建了你的Providers
文件和组件,但没有在使用它。
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<Providers>
<Header />
{children}
</Providers>
</body>
</html>
);
}
英文:
You have created your Providers
file and component, but are not using it.
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<Providers>
<Header />
{children}
</Providers>
</body>
</html>
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论