So I'm setting up a react useContext to share user's data such as the user's name and the login status etc... I make a request to the server every time a user refreshes the app to verify that if they have a valid token, the user can then be logged in. Great, but one problem I keep on running into with react is knowing how to get an instant update of useState, as this is needing to be updated as soon as the user is verified.
I've read that you have to create a new object so that React knows it's a new object and then it'll trigger a re-render... Just about every combination I can think of I've tried. Can someone please clarify for me how it's done?
Option 1:
setUser(prev => {
return { ...prev, ...newObj }
})
Option 2:
setUser({ ...newObj })
Can someone please give me the proper way to get a instant update to the React useState.
Thanks
import React, { useState } from "react";
import { useReadCookie } from "../hooks/cookies";
import UserContext from "./user-context";
const UserContextProvider = ({ children }) => {
const readCookie = useReadCookie;
const [user, setUser] = useState({
name: null,
userID: null,
token: null,
permissions: null,
loginStatus: false,
checkLoginStatusReady: false,
});
const loginStatus = async () => {
return new Promise(async (resolve, rej) => {
// So we'll reach out to the server and check to see if the
// User is logged in
const token = readCookie("token");
if (token && token.length === 174) {
// send a request to see if this is a valid user
const req = await fetch("/api/checkLoginStatus.php");
const res = await req.json();
// console.log(res);
handleLogUserIn(res);
}
console.log(user, "The state variable");
resolve();
});
};
const handleLogUserIn = (res) => {
if (res.success === true) {
const userObj = {
name: res.name,
userID: res.userID,
token: res.token,
permissions: res.permissions,
loginStatus: true,
checkLoginStatusReady: true,
};
console.log(userObj, "the user variable");
setUser({ ...userObj });
}
else {
console.log("Not going here");
const userObj = {
name: null,
userID: null,
token: null,
permissions: null,
loginStatus: false,
checkLoginStatusReady: true,
};
setUser({ ...userObj });
}
};
return (
<UserContext.Provider
value={{
username: user.username,
userID: user.userID,
token: user.token,
permissions: user.permissions,
loginStatus: user.loginStatus,
checkLoginStatusReady: loginStatus,
setUser,
}}
>
{children}
</UserContext.Provider>
);
};
export default UserContextProvider;
CodePudding user response:
you can use useEffect for listening to the state update example if using
const [state, setState] = useState({
username : "",
status : "",
})
useEffect(() => {
setState({
...state,
username : state.username,
status : "active,
})
},[state])
or if using context : On parent provider.js:
import React, { useState } from 'react'
export const UserContext = React.createContext({
username: "",
status: "active",
setUser: () => {}
})
export const UserContextProvider = (props) => {
const setUser = (param) => {
setState({...state, username: param.username, status: param.status})
}
const initState = {
username: "",
status: "active",
setUser: () => {}
}
const [state, setState] = useState(initState)
return (
<UserContext.Provider value={state}>
{props.children}
</UserContext.Provider>
)
}
On Component:
import React, { useContext } from 'react'
import provider from './provider'
function Component() {
const context = useContext(provider.UserContext)
const onClick = () => {
// do hit api
if(token){
state.setUser({username : "a", status:"inactive"})
}
}
return (
<provider.UserContextProvider>
<buttin onClick={onClick}></button>
<div>username : {state.username}</div>
<div>status : {state.status}</div>
</provider.UserContextProvider>
)
}