React JS:如何将NavBar组件的用户信息传递到Products组件
如何在React组件间共享用户登录信息
下面提供三种实用的方案,帮你把NavBar里的用户信息传递到Products组件:
方案一:状态提升到共同父组件
把用户信息的获取和状态管理移到NavBar与Products的共同父组件(比如App.js),再通过props传递给两个子组件,适合简单的组件层级结构:
- 改造父组件(以App.js为例):
import React, { useState, useEffect } from 'react'; import NavBar from './NavBar'; import Products from './Products'; function App() { const [userInfo, setUserInfo] = useState(); useEffect(() => { (async () => { setUserInfo(await getUserInfo()); })(); }, []); async function getUserInfo() { try { const response = await fetch('/.auth/me'); const payload = await response.json(); const { clientPrincipal } = payload; return clientPrincipal; } catch (error) { console.error('No profile could be found'); return undefined; } } return ( <div className="app-container"> <NavBar userInfo={userInfo} /> <Products userInfo={userInfo} /> </div> ); } export default App;
- 修改NavBar组件,移除自身的状态逻辑,直接接收props中的userInfo:
import React from 'react'; import { NavLink } from 'react-router-dom'; const NavBar = ({ userInfo, children }) => { const providers = ['twitter', 'github', 'aad']; const redirect = window.location.pathname; return ( <div className="column is-2"> <nav className="menu"> <p className="menu-label">Menu</p> <ul className="menu-list"> <NavLink to="/products" activeClassName="active-link"> Recipes </NavLink> <NavLink to="/about" activeClassName="active-link"> Help </NavLink> </ul> {children} </nav> <nav className="menu auth"> <p className="menu-label">LOGIN</p> <div className="menu-list auth"> {!userInfo && providers.map((provider) => ( <a key={provider} href={`/.auth/login/${provider}?post_login_redirect_uri=${redirect}`}> {provider} </a> ))} {userInfo && <a href={`/.auth/logout?post_logout_redirect_uri=${redirect}`}>Logout</a>} </div> </nav> {userInfo && ( <div> <div className="user"> <p>Welcome</p> <p>{userInfo.userDetails}</p> <p>{userInfo.identityProvider}</p> </div> </div> )} </div> ); }; export default NavBar;
- 在Products组件中接收并使用userInfo:
// Products.js import React from 'react'; const Products = ({ userInfo }) => { // 保留你原有的handleCancelProduct、handleSave等逻辑 return ( {/* 保留你原有的其他JSX代码 */} <footer className="card-footer "> <ButtonFooter className="cancel-button" iconClasses="fas fa-undo" onClick={handleCancelProduct} label="Cancel" /> <ButtonFooter className="save-button" iconClasses="fas fa-save" onClick={handleSave} label="Save" /> {userInfo && <span> Posted By: {userInfo.userDetails}</span>} </footer> {/* 保留你原有的其他JSX代码 */} ); }; export default Products;
方案二:使用React Context API(全局状态)
如果你的应用有多个组件需要共享用户信息,用Context可以避免层层传递props的麻烦:
- 创建用户上下文文件(contexts/UserContext.js):
import React, { createContext, useState, useEffect, useContext } from 'react'; const UserContext = createContext(); export function UserProvider({ children }) { const [userInfo, setUserInfo] = useState(); useEffect(() => { (async () => { setUserInfo(await getUserInfo()); })(); }, []); async function getUserInfo() { try { const response = await fetch('/.auth/me'); const payload = await response.json(); const { clientPrincipal } = payload; return clientPrincipal; } catch (error) { console.error('No profile could be found'); return undefined; } } return ( <UserContext.Provider value={{ userInfo }}> {children} </UserContext.Provider> ); } export function useUser() { return useContext(UserContext); }
- 在根组件(App.js)中包裹Provider:
import React from 'react'; import { UserProvider } from './contexts/UserContext'; import NavBar from './NavBar'; import Products from './Products'; function App() { return ( <UserProvider> <div className="app-container"> <NavBar /> <Products /> </div> </UserProvider> ); } export default App;
- 修改NavBar组件,用useUser钩子获取用户信息:
import React from 'react'; import { NavLink } from 'react-router-dom'; import { useUser } from './contexts/UserContext'; const NavBar = ({ children }) => { const providers = ['twitter', 'github', 'aad']; const redirect = window.location.pathname; const { userInfo } = useUser(); return ( {/* 原有的JSX代码完全保留,直接使用userInfo即可 */} <div className="column is-2"> {/* 原代码内容 */} </div> ); }; export default NavBar;
- 在Products组件中使用useUser钩子:
// Products.js import React from 'react'; import { useUser } from './contexts/UserContext'; const Products = () => { const { userInfo } = useUser(); // 保留你原有的handleCancelProduct、handleSave等逻辑 return ( {/* 保留你原有的其他JSX代码 */} <footer className="card-footer "> <ButtonFooter className="cancel-button" iconClasses="fas fa-undo" onClick={handleCancelProduct} label="Cancel" /> <ButtonFooter className="save-button" iconClasses="fas fa-save" onClick={handleSave} label="Save" /> {userInfo && <span> Posted By: {userInfo.userDetails}</span>} </footer> {/* 保留你原有的其他JSX代码 */} ); }; export default Products;
方案三:封装独立工具函数(各自获取)
如果不需要实时同步登录状态,也可以把获取用户信息的逻辑抽成独立函数,让两个组件各自调用:
- 创建工具函数文件(utils/auth.js):
export async function getUserInfo() { try { const response = await fetch('/.auth/me'); const payload = await response.json(); const { clientPrincipal } = payload; return clientPrincipal; } catch (error) { console.error('No profile could be found'); return undefined; } }
- 修改NavBar组件,导入并使用这个函数:
import React, { useState, useEffect } from 'react'; import { NavLink } from 'react-router-dom'; import { getUserInfo } from './utils/auth'; const NavBar = ({ children }) => { const providers = ['twitter', 'github', 'aad']; const redirect = window.location.pathname; const [userInfo, setUserInfo] = useState(); useEffect(() => { (async () => { setUserInfo(await getUserInfo()); })(); }, []); return ( {/* 原有的JSX代码完全保留 */} <div className="column is-2"> {/* 原代码内容 */} </div> ); }; export default NavBar;
- 在Products组件中调用函数获取用户信息:
// Products.js import React, { useState, useEffect } from 'react'; import { getUserInfo } from './utils/auth'; const Products = () => { const [userInfo, setUserInfo] = useState(); // 保留你原有的handleCancelProduct、handleSave等逻辑 useEffect(() => { (async () => { setUserInfo(await getUserInfo()); })(); }, []); return ( {/* 保留你原有的其他JSX代码 */} <footer className="card-footer "> <ButtonFooter className="cancel-button" iconClasses="fas fa-undo" onClick={handleCancelProduct} label="Cancel" /> <ButtonFooter className="save-button" iconClasses="fas fa-save" onClick={handleSave} label="Save" /> {userInfo && <span> Posted By: {userInfo.userDetails}</span>} </footer> {/* 保留你原有的其他JSX代码 */} ); }; export default Products;
内容的提问来源于stack exchange,提问作者Djdjsj
相关产品推荐
相关产品推荐

