从 children 反应设置父状态

Posted

技术标签:

【中文标题】从 children 反应设置父状态【英文标题】:React set parent state from children从 children 反应设置父状态 【发布时间】:2021-03-21 22:07:50 【问题描述】:

您好,我正在尝试构建一个加载容器组件

   export const LoadingContainer = () =>
   const [isLoading,setIsLoading] = useState(false)
    return(<div className="loading-container">
      children
      isLoading ? <LoadingSVG>  : ""
    </div>)
    

但我想知道是否有办法从 children 调用 setIsloading 像这样

<LoadingContainer>
  <div className="tes">
    <button onClick=setIsLoading(true)>Start Loading</button> 
 </div>
</LoadingContainer>

【问题讨论】:

【参考方案1】:

作为孩子的功能

解决此问题的众多方法之一是使用 function as a child 模式,Context.Consumer 使用该模式。

现在您将子元素作为普通 JSX 元素传递,例如:

<LoadingContainer>
   <SomeChild/>
</LoadingContainer>

我们可以改为让 child 成为接收 setIsLoading 作为其参数的函数。这使您可以编写如下内容:

<LoadingContainer>
  (setIsLoading) => (
     <div className="tes">
       <button onClick=() => setIsLoading(true)>Start Loading</button> 
     </div>
  )
</LoadingContainer>

由于children 现在是一个函数而不是一个元素,您现在可以在您的LoadingContainer 中调用它并提供setIsLoading 参数。

export const LoadingContainer = () => 
   const [isLoading, setIsLoading] = useState(false);

   return(
     <div className="loading-container">
      isLoading ? <LoadingSVG/> : children(setIsLoading)
    </div>
   )


如果您想一直显示children,而不仅仅是当isLoadingfalse 时,您可能希望同时传递isLoadingsetIsLoading。所以我们可以将它们作为对象的两个属性传递。

<LoadingContainer>
  (isLoading, setIsLoading) => (
     <div className="tes">
       <button onClick=() => setIsLoading(!isLoading)>
         isLoading ? "Stop Loading" : "Start Loading"
       </button> 
     </div>
  )
</LoadingContainer>
export const LoadingContainer = () => 
   const [isLoading, setIsLoading] = useState(false);

   return(
     <div className="loading-container">
      isLoading && <LoadingSVG/>
      children(isLoading, setIsLoading)
    </div>
   )

【讨论】:

这正是我所需要的,谢谢!我从未考虑过这种方法(我还有很多东西要学)【参考方案2】:

[更新]

您可以使用渲染道具 (https://reactjs.org/docs/render-props.html)。

并将 setIsLoading 函数向下传递给渲染函数。

[原创]

如果使用上下文感觉有点矫枉过正,您可以将 setIsLoading 作为道具传递给子组件。

【讨论】:

【参考方案3】:

您可以使用上下文 API:https://reactjs.org/docs/context.html

它看起来像这样:

const YourContext = React.createContext();

<YourContext.Provider value=isLoading, setIsLoading>
  // body
</YourContext.Provider>

在子组件中你可以使用 useContext 钩子。

const [isLoading, setIsLoading] = useContext(YourContext)
setState('something')

【讨论】:

但是如果我在页面中有多个容器需要加载,那么加载是否会同时应用于它们?或者如果我将它们与 Context 分开包装,加载将单独处理 setState 将在每个使用状态值的地方触发重新渲染。但是您必须包装将使用该状态的所有组件。否则,您将在每个上下文中获得不同的值。 从技术上讲,这就是我想要的,假设有 2 个容器 sx 和 dx,我想让装载机出现在不同的时间 所以,我看到了 3 个解决方案: 1. 直接将带有 setState 的道具传递给子组件。 2. 创建 2 个具有单独状态的上下文。 3.也许Suspense组件会解决你的问题:reactjs.org/docs/concurrent-mode-reference.html#suspense

以上是关于从 children 反应设置父状态的主要内容,如果未能解决你的问题,请参考以下文章

从两个集合创建父级 -> 子级层次结构

反应:你怎么能设置一个嵌套的孩子的状态

在设置子组件的数组状态并将其通过反应测验传递回父组件时出现问题

反应路由器和 this.props.children - 如何将状态传递给 this.props.children

如何从反应中的子组件内部更改父组件的背景颜色,盖茨比

将异步结果从父组件传递给子组件反应功能组件