skip to Main Content

I’m trying to learn TypeScript. I’m able to do a simple useState hook on a simple page. However when I want to be able to set state using context I can’t get it to set the state properly as is shown by its inability to re-render on the page.

App.tsx


export interface User {
  isSubscribed: boolean;
  name: string;


}


const App: React.FC = () => {

  const [user, setUser] = useState<User>({
    isSubscribed: true,
    name: 'You',
  })

  return(


  <IonApp>
    <IonReactRouter>
      <IonRouterOutlet>
        <DashboardContext.Provider value={{user, setUser}}>
        <Route exact path="/home">
          <Home />
        </Route>
        <Route exact path="/">
          <Redirect to="/home" />
        </Route>
        </DashboardContext.Provider>
      </IonRouterOutlet>
    </IonReactRouter>
  </IonApp>
)
};

export default App;

context.tsx:

export interface DashboardInterface {
    user: User
    setUser: Dispatch<SetStateAction<User>>
}

export const DashboardContext = createContext<DashboardInterface>(undefined);


export function useUserContext() {
    const {user, setUser} = useContext(DashboardContext)
    if (user===undefined){
        throw new Error("useUserContext must be used with a Dashboard Context")
    }
    return {user, setUser}
}

Home.tsx

const Home: React.FC = () => {

  interface Thing {
    title: string;
    nickname: string
  }

  const {user, setUser }= useUserContext()
  const [thing, setThing]=useState<Thing>({
    title: "Mr",
    nickname: "Morale",
  })

  useEffect(() => {
    console.log("in the useEffect")

  },[user])

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>User {user.name} {thing.nickname}</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Blank</IonTitle>
          </IonToolbar>
        </IonHeader>
        
        <IonButton onClick={()=>{setUser({isSubscribed: false, name: "Pete"}); console.log('clicked!', user); setThing({title: "Mrs", nickname:"Morales"})}}>
          Change Name
        </IonButton>
        
        <ExploreContainer />
      </IonContent>
    </IonPage>
  );
};

export default Home;

Here in Home.tsx I have a button that when I push it I expect it to change the user.name to "Pete" and the Thing.nickname to "Morales" as can be displayed in the component.

when I click the button. Only thing.nickname changes from Morale to Morales. (Thing is something I set up all on the Home.tsx page). However user.name stays the same as "You" (user is something I set up on App.tsx and context.tsx.) Therefore, I think I am doing something wrong with using context. Any ideas as to what I’m doing wrong?

2

Answers


  1. Chosen as BEST ANSWER

    I just had to move my provider outside !


  2. Try something like the code below to observe your user variable. It will run when the user value is changed. If the logged user variable is updated, then you might want to look at your rendering.

    import React, { useState, useEffect } from 'react';
          
    useEffect(() => {
      console.log('user:', user);
    }, [user]);
    

    If the user doesn’t change, try removing the context and using useState within the Home component to see if the state updates as expected. This removal can help isolate whether the issue is in the context setup or with the state update logic.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search