I'm not sure why but for some reason I don't have the value of old state when calling update, it always seems to have the value of default state.
const defaultState:RootState = {
loadSessions:(groupId:string,lectureId:string)=>{},
loadSession:(sessionId:string)=>()=>{},
userJoined:(user:IUser)=>{}
};
const TSessionContext = React.createContext<RootState>(defaultState);
export const TSessionProvider: FC = ({ children }) => {
const [state, setState] = useState<RootState>(defaultState);
const loadSession = (sessionId:string)=>{
console.info("Calling load session");
const unsubSession = db.collection(COLLECTION_REF).doc(sessionId)
.onSnapshot((snapshot) => {
const session = snapshot.data() as ISession;
console.info("setting session",state);
setState({
...state,
session
});
});
const unsubUsers = db.collection(`${COLLECTION_REF}/${sessionId}/users`)
.onSnapshot((querySnapshot) => {
const users:IUser[] = [];
querySnapshot.forEach((doc) => {
users.push(doc.data() as IUser)
});
console.info("setting users",state);
setState({
...state,
users
});
});
return ()=>{
unsubUsers();
unsubSession();
};
}
return (
<TSessionContext.Provider
value={{
...state,
loadSession,
}}
>
{children}
</TSessionContext.Provider>
);
};
export const useTSession = () => useContext(TSessionContext);
Here I always get output "setting session" with default state value and "setting users" with default state value.
Code where I am using this hook:
const {loadSession,session,users} = useTSession();
useEffect(()=>{
if(sessionId&&!session){
const unsub = loadSession(sessionId);
return () => {
unsub()
}
}
},[]);
Then in my main component I get session first with user undefined.
And then user with session undefined.
If I add another hook that fetches more data, then it has the same issue. So I'm really not sure what is the problem here.
If I split my hooks internal state like this:
const [iSession, setISession] = useState<any>();
const [iUser, setIUser] = useState<any>();
return (
<TSessionContext.Provider
value={{
...state,
users:iUser,
session:iSession,
loadSession,
}}
>
{children}
</TSessionContext.Provider>
);
Then it seems to work correctly, not sure why the other variant doesn't.