Nextjs:如何使用具有多个值的 ContextAPI,所有这些值都需要从子组件中更新

Posted

技术标签:

【中文标题】Nextjs:如何使用具有多个值的 ContextAPI,所有这些值都需要从子组件中更新【英文标题】:Nextjs: How to use ContextAPI with multiple values all of which need to be updated from child components 【发布时间】:2021-08-10 23:07:08 【问题描述】:

我在上下文提供程序包装函数中存储了三个值。我需要更新登录和注销组件中的上下文状态,并在导航栏和任何其他地方使用它们。

const AppContext = createContext();

const AppContextProvider = (props) => 
    const loggedIn = Cookies.get('isLoggedIn') ? true : false;
    const [ isLoggedIn, setIsLoggedIn ] = useState(isLoggedIn);
    const [ userID, setUserID ] = useState('');
    const [ email, setEmail ] = useState('');

    return (
        <AppContext.Provider value=[isLoggedIn, setIsLoggedIn, userID, setUserID, email, setEmail ]>
            props.children
        </AppContext.Provider>
    );


export  AppContext, AppContextProvider ;

_app.js 中是这样的:

function MyApp( Component, pageProps ) 
  return (
    <>
      <AppContextProvider>
        <NavBar />
        <Component ...pageProps />
        <Footer />
      </AppContextProvider>
    </>
  );

但是现在,问题是,我无法理解如何更新这些上下文状态。这是我在登录组件中的用例:

const [ isLoggedIn, setIsLoggedIn, userID, setUserID, email, setEmail ] = useContext(AppContext);
const handleSubmit = async() => 
    const url = process.env.NEXT_PUBLIC_URL + 'auth/login/';
    const data =  "email": email, "password": password ;
    try 
        const resp = await axios.post(url, data);
        const obj = await resp.data;
        Cookies.set('isLoggedIn', true,  secure: true ,  sameSite: 'lax' );
        setIsLoggedIn(true);
        setUserID(obj.uid);
        setEmail(obj.email);
     catch (err) ...;

这样,它不起作用。我无法在其他组件中获取上下文值。如何更新多个上下文状态?

编辑:

根据@Drew Reese 的回答,这是我的工作上下文文件:

import Cookies from 'js-cookie';
import  useState, createContext  from 'react';

const AppContext = createContext(
    email:'',
    isLoggedIn: false,
    userID: '',
    setEmail: () => ,
    setIsLoggedIn: () => ,
    setUserID: () => ,
);

const AppContextProvider = (props) => 
    const [ email, setEmail ] = useState(Cookies.get('email') || null);
    const [ userID, setUserID ] = useState(Cookies.get('uid') || null);
    const [ isLoggedIn, setIsLoggedIn ] = useState(Cookies.get('isLoggedIn') ? true : false);

    return (
        <AppContext.Provider value= email, setEmail, isLoggedIn, setIsLoggedIn, userID, setUserID >
            props.children
        </AppContext.Provider>
    );


export  AppContext, AppContextProvider ;

【问题讨论】:

【参考方案1】:

您的默认上下文值应符合消费者的期望。

Updating Context from a Nested Component

经常需要从一个组件更新上下文 嵌套在组件树深处的某个地方。在这种情况下,您可以 通过上下文向下传递函数以允许消费者更新 上下文:

// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const ThemeContext = React.createContext(
  theme: themes.dark,
  toggleTheme: () => ,
);

更新您的 AppContext 默认值以匹配消费者将使用的内容。

const AppContext = createContext([
  false,    // isLoggedIn
  () => , // setIsLoggedIn
  '',       // userID
  () => , // setUserID
  '',       // email
  () => , // setEmail
]);

使用这样的数组可能有点麻烦,消费者在使用解构赋值时需要保持数组索引的正确性。使用一个对象来代替使用上下文值变得更加有用,现在顺序无关紧要了。

const AppContext = createContext(
  email: '',
  isLoggedIn: false,
  userID: '',
  setEmail: () => ,
  setIsLoggedIn: () => ,
  setUserID: () => ,
);

用法:

const 
  isLoggedIn,
  setIsLoggedIn,
  userID,
  setUserID,
  email,
  setEmail,
 = useContext(AppContext);

我无法获取其他组件中的上下文值。我如何能 更新多个上下文状态?

您应该确保您希望能够更新上下文值的所有消费者实际上嵌套在同一个AppContextProvider 组件中。

【讨论】:

如何通过我的AppContextProvider() 包装函数传递这些AppContext 对象? @forest 您传递上下文值的方式与以前相同,value=[isLoggedIn, setIsLoggedIn, userID, setUserID, email, setEmail],如果您接受我的建议,则将其作为对象传递,value= isLoggedIn, setIsLoggedIn, userID, setUserID, email, setEmail @forest userEmail 是什么?它没有在您的代码 sn-p 中的任何地方定义。这是您的服务器在 POST 请求数据中所期望的某事吗,例如const data = "userEmail": email, "password": password ; 好吧,实际上我错过了在AppContextProvider() 函数中将其定义为useState()。现在它正在工作。更新我的答案。谢谢!

以上是关于Nextjs:如何使用具有多个值的 ContextAPI,所有这些值都需要从子组件中更新的主要内容,如果未能解决你的问题,请参考以下文章

如何使用在 Nextjs 上的窗口加载事件上返回本地存储值的函数初始化状态? [复制]

Next js中具有多个参数的动态路由

NextJS 使用带有布局组件包装器的 React 的 Context API

如何使用 Flutter 在 Firestore 中删除具有特定值的多个文档

在 NextJS 应用程序中使用 React Context API 会禁用静态站点生成器吗?

如果使用func()具有多个输出,如何获得函数输出的长度?