Tengo el siguiente archivo UserContext.js, que almacena el usuario conectado actual en un objeto de usuario, y también una función de establecimiento. En mi componente de perfil, quiero completar previamente mis campos de entrada con la información del usuario que ha iniciado sesión actualmente, que debería obtener usando ganchos useContext.
La aplicación funciona bien si navego a la página de perfil normalmente desde la página de inicio, pero cuando trato de acceder directamente a /profile o volver a cargar la página mientras estoy en la página de perfil, veo que mi contexto se vuelve indefinido por una fracción de segundo (como se ve por el archivo console.log), antes de que cargue un valor. Esto hace que el gancho useEffect() y la función initializeFields() fallen porque las propiedades son nulas.
Lo que quiero que suceda es poder cargar sin problemas el usuario que ha iniciado sesión actualmente y también usarlo globalmente en otros componentes dentro de la aplicación. Pasar el objeto de usuario del componente principal como accesorios no es factible porque, en realidad, mi aplicación tiene algunos componentes de profundidad y la exploración de accesorios no sería una solución muy elegante.
const UserContext = React.createContext({ user: {}, setUser: (user) => {}, });En el componente App.js:
const App = (props) => { const [user, setUser] = useState(null); return ( <div className="app"> <UserContext.Provider value={{ user, setUser }}> <Switch> <Route path="/profile" exact component={Profile} /> </Switch> </UserContext.Provider> </div> );El componente Profile.js:
const DashboardProfileModal = (props) => { const userContext = useContext(UserContext); const [name, setName] = useState(); const [username, setUsername] = useState(); const [password, setPassword] = useState(); const [address, setAddress] = useState(); console.log(userContext) useEffect(() => { initializeFields(); }); const initializeFields = () => { setName(userContext.user.name); setUsername(userContext.user.username); setPassword(userContext.user.password); setAddress(userContext.user.address); };Podría hacer algo como a continuación y asegurarse de que userContext esté disponible antes de intentar usarlo.
También debe al menos hacer que useEffect se ejecute una vez en la carga de la página agregando [] (de lo contrario, se activará constantemente en cada procesamiento). También agregué userContext como una dependencia de useEffect y luego userContext y name . Esto significa que se asegurará de que userContext no sea null antes de intentar ejecutar su método.
Luego, también incluyo la verificación de !name para que podamos asegurarnos de que no siga intentando ejecutar su método una vez que su estado se haya establecido por primera vez.
const DashboardProfileModal = (props) => { const userContext = useContext(UserContext); const [name, setName] = useState(); const [username, setUsername] = useState(); const [password, setPassword] = useState(); const [address, setAddress] = useState(); console.log(userContext) useEffect(() => { if(userContext && !name){ initializeFields(); } },[userContext]); const initializeFields = () => { setName(userContext.user.name); setUsername(userContext.user.username); setPassword(userContext.user.password); setAddress(userContext.user.address); };Creo que el problema al que se enfrenta es porque tiene el proveedor declarado en el componente de la App . Si desea que sea accesible globalmente para toda la aplicación, debe tenerlo en su archivo index.js , envolviendo el componente de la App . Algo como:
ReactDOM.render( <React.StrictMode> <UserContext.Provider> <App /> </UserContext.Provider> </React.StrictMode>, document.getElementById("root") )