Nextjs:如何将 ContextAPI 与多个值一起使用,所有这些值都需要从子组件更新

Nextjs: How to use ContextAPI with multiple values all of which need to be updated from child components

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

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

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

Updating Context from a Nested Component

It is often necessary to update the context from a component that is nested somewhere deeply in the component tree. In this case you can pass a function down through the context to allow consumers to update the context:

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

I could not get the context values in other components. How do I update multiple context states?

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