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