I need help updating a user within various parts of my react app. I have successfully been able to create a context and access it globally, but anytime I try to update the state, it either breaks or uses default state I have issues updating the state, the code goes here
Context File
import { createContext } from "react"; const user = { Fullname: "Ade Johnson", username: "Jonny", phone: " 234 0987655", email: "[email protected]", mode: "light", isLoggedIn: false, }; export const UserContext = createContext(user);
App.js
import { UserContext } from "../User"; const providerValue = useMemo(() => ({ user, setUser }), [user, setUser]); const { user, setUser } = useContext(UserContext); <UserContext.Provider value={providerValue}> {Children} </UserContext.Provider>
3.Login.js
function Login() {
const [username, setUsername] = useState("");
const [pass, setPass] = useState("");
const { user, setUser } = useContext(UserContext);
function proceed(url) {
let newArr = {...user};
newArr[0].isLoggedIn = true;
newArr[0].Fullname = "Toluwalope";
newArr[0].username = "Toolz";
newArr[0].email = "[email protected]";
setUser(newArr);
console.log(user);
window.location.replace(url);
}
Dashboard.js
import React, { useContext, useEffect } from "react"; import { UserContext } from "../User"; function Dashboard() { const { user } = useContext(UserContext); return ( <div className="container-fluid" id="main"> <h5 className="mt-5 pt-5">Welcome {user[0].username},</h5> </div> ); }; export default Dashboard;
At this point, When the dashboard is loaded, it uses the default state.
CodePudding user response:
You're mixing up your data structures. You should destructure from useContext
with an array (not an object), and your user
object should be an object (not an array):
const [user, setUser] = useContext(UserContext);
And
const newUser = { ...user, isLoggedIn: true }; // etc
CodePudding user response:
Context.jsx
import React from 'react'
export const Store = React.createContext({})
export default function StoreProvider({children}){
const [user, setUser] = React.useState({...you user properties})
return(
<Store.Provider value={{
user, setUser
}}
>
{children}
</Store.Provider>
)
}
App.jsx
import StoreProvider from 'path/to/store_provider.jsx'
export default function App(){
return (
<StoreProvider>
//here you add your components that you want
// to have access to the store or your router
</StoreProvider>
)
}
Login.jsx
import React from 'react'
import {Store} from 'path/to/store'
export default function Login(){
//now you can update user successfully like this
// setUser(prev => {...prev, newKey: newValue})
const {setUser} = React.useContext(Store)
return (
//your jsx here
)
}
Dashboard.jsx
import React from 'react'
import {Store} from 'path/to/store'
export default function Dashboard(){
//now you can read user successfully like so
// user.FirstName etc.
//updating user from other components will update this view automatically
const {user} = React.useContext(Store)
return (
//your jsx here
)
}
Your code in general doesn't compile the way you are showing it to us. But even if you omitted some parts, there are two flaws.
- You are passing user directly to the StoreProvider value which means that you can destructure Fullname, username etc. from the store and not {user, setUser}
- You are not passing setUser to the StoreProvider value which means that you can't destructure it, and can't update your state. Later you do something with useMemo() but this is iffy. It may work, it may not, or it may cause bugs. Usually you want to pass a state or a reducer to the StoreProvider value.
Also useMemo() is not needed. Check docs for the most suitable usecases of useMemo().