【问题标题】:useContext - Child component loses state after parent state is changeduseContext - 子组件在父状态更改后丢失状态
【发布时间】:2022-12-12 23:10:59
【问题描述】:

这是我的应用程序结构的伪代码示例。我正在尝试与 React 上下文全局共享状态,但在顶层更新状态会导致子组件重新渲染和重置状态(我认为)出现问题。

// 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 {
    ...
  }
}

我的问题:

这是一个好的应用程序结构,还是有问题?我可以做些什么来将状态保留在 Child componenet 中,还是我需要以某种方式将共享状态移出 App.js?

【问题讨论】:

  • 首先,您不允许更新渲染方法中的任何状态,您在 Child 中违反了这一点。从举一个合适的例子开始。
  • 当父状态发生变化时,子状态将始终卸载,您可以将子状态移动到父/上下文或尝试使用外部状态管理库,如 jotai
  • @super 正如我在问题中所述,它是伪代码。我不想问语法,而是项目结构。
  • @JackA7X 我没有指出语法。我指出了导致您所描述的行为的代码中的结构错误。

标签: reactjs


【解决方案1】:

您构建的 useContext 错误。您可以查看 React hooks 如何使用它。

一个可能对您有帮助的全功能示例是:

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 };

那么你所要做的就是包装你想要的所有组件(孩子),例如包装&lt;App /&gt; 所以,或多或少的一切:

 <AppProvider>
      <App />
 </AppProvider>

所以现在在这种情况下,您可以在所有代码中使用 AppContext 中的所有内容,如果需要,您可以传递更多变量和函数,然后使用以下方法导入:

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()

【讨论】:

  • 这正是我需要的,谢谢!立即解决了我的错误并帮助我清理了很多代码。
【解决方案2】:

像道具一样提供从父母到孩子的状态,它比 useContext 更大。

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

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

并且子组件具有以下形式

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

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

  return {
    ...
  }
}

【讨论】:

    猜你喜欢
    • 2021-06-27
    • 2019-07-12
    • 2016-10-02
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2018-10-16
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多