Home > Net >  Child component loses state after parent state is changed
Child component loses state after parent state is changed

Time:12-06

Here is a pseudo code example of my app structure. I am trying to share state globally with react context, but updating state at the top level is causing issues with Child components re-rendering and resetting state (I think).

// My top level where I store the state all other components need

function App() {
  const [userData, setUserData] = useState()

  const userContext = {
    userData,
    setUserData
  }

  return (
    <App>
      <Context.Provider value={userContext}>
        <Child />
        <Child />
        <Child />
      </Context.Context.Provider>
    </App>
  )
}



// My child component where I want to preserve state

const Child = () => {
  const [childState, setChildState] = useState('default value')

  // I want to keep this value
  setChildState('new value')

  // This is causing App.js to re-render, then Child to rerender, and I lose child state. Then on the next render my 'childState' is back to 'default value', when I want it to still be 'new value'
  const userContext = useContext(...)
  userContext.setUserData('some change to userdata')

  return {
    ...
  }
}

My questions:

Is this an okay app structure, or is there a problem with it? Is there something I can do to persist the state in the Child componenet, or do I need to move the shared state out of App.js somehow?

CodePudding user response:

You have structured the useContext wrong. You can check in React hooks how to use it.

One example with full-functionality which it may help you is:

const AppContext = React.createContext();

const AppProvider = ({ children }) => {
const [userData, setUserData]=useState('nothing here')

// any code you want to pass in the code
//e.g. a function
const randomFunction = ()=>{
//do something here
}

 return (
    <AppContext.Provider
      value={{
       userData,
       setUserData,
       randomFunction
      }}
    >
      {children}
    </AppContext.Provider>
  );
};

export const useGlobalContext = () => {
  return useContext(AppContext);
};

export { AppContext, AppProvider };

then all you have to do is to wrap all the components (children) you want, e.g. wrap <App /> so, more or less everything:

 <AppProvider>
      <App />
 </AppProvider>

So now in this case you can use everything from your AppContext in all your code, you can pass more variables and functions if you want, and you import that by using:

import { useGlobalContext } from '/pathYouHaveIt';

function App() {
  const {
       userData,
       setUserData,
       randomFunction,
  } = useGlobalContext();

// now you can use those like you have them set-up in the App()

CodePudding user response:

Provide state from parent to child like props, it wood be greater than useContext.

function App() {
  const [userData, setUserData] = useState()

  return (
    <div className="App">
      <Child userData={userData}, setUserData={setUserData}/>
    </div >
  )
}

And the child component has the form

const Child = ({userData, setUserData}) => {
  const [childState, setChildState] = useState('default value')

  setChildState('new value')
  setUserData('some change to userdata')

  return {
    ...
  }
}
  • Related