在没有关系的 React 组件之间共享数据?

Posted

技术标签:

【中文标题】在没有关系的 React 组件之间共享数据?【英文标题】:Share data between React components with no relation? 【发布时间】:2019-02-09 21:39:51 【问题描述】:

我正在开发一个 React 组件库,它允许通过将对象数组和 <input/> 作为道具传递给 <SearchFilter/> 组件来进行客户端数据过滤。我想将过滤后的结果返回到一个 separate <SearchResults/> 组件,该组件可以在树的其他位置呈现(即结果组件不必是输入组件的子组件)。

我已经弄清楚了过滤器,但我不确定在 React 中将过滤后的数据发送到 <SearchResults/> 组件的最佳途径。

这就是我想要的结果......

<SearchFilter
  data=data
  input=<input type="text" value=value onChange=this.handleChange/>
/>

然后,使用 Render Props 返回数据并映射到返回 JSX,就会有结果组件。像这样的...

<SearchResults 
  render=data => (
    data.map(el => (
      <div>
       <span>data.someProperty</span>
      </div>
    )
  )
/>

这是我想要实现的,因为我希望允许在树中的一个位置渲染 &lt;SearchFilter/&gt; 组件,并允许在 其他地方 渲染 &lt;SearchResults/&gt; 组件,这样树的组合方式以及视图的呈现方式就具有最大的灵活性。

我研究了 Context API,但似乎需要更多的组件才能成为我的库的一部分,这使我想要实现的目标更加复杂。如果这是解决它的唯一方法,那很好,但我想问问是否有人能想到其他解决方案。

谢谢!

【问题讨论】:

某种状态管理系统是不可避免的。不要将 Redux 视为一个过度设计的解决方案,如果您现在是这样认为的。 Redux 有大量样板文件,但是您对整个 Web 应用程序中的数据流的控制是完全值得的。老实说,我什至无法想象在没有 Redux 的情况下制作 React 应用程序 【参考方案1】:

更大的问题是,您需要管理在更高级别的组件之间共享的状态,即最终包装这两个组件的任何组件。使用普通 React,此状态将由父(或祖先)组件管理,将相关值作为 props 传递。这与让兄弟组件影响彼此状态的想法通常很糟糕,因为您很容易陷入“谁是这里的老板”问题。

Context API 处理的事情是不必为通常不会改变的事情(或者:通常不应该导致渲染经常触发)传递道具。

全局状态存储,例如 Redux,可以帮助您对此进行建模,但本质上它只是管理状态的“一个”组件,以及根据该状态呈现的其他组件。底层组件内的事件触发数据的变化,会导致状态发生变化,从而导致children的props发生变化,进而导致重新渲染。

我建议你尝试使用这个简单的模式:

class Search ... 
    state = data: [], text: ""

    render() 
        return (
            <div>
                <SearchFilter 
                    data=this.state.data 
                    onSearch=() => this.fetchNewData() 
                    onChange=(e) => this.setState(text: e.targetElement.value)
                    text=this.state.text 
                />
                <SearchResults data=this.state.data />
            </div>
        );
    

    fetchNewData() 
        fetch('/url?text=' + this.state.text)
            .then((newData) =>  this.setState(data: newData); )
    

类似的东西。如果你在建模这样的东西时遇到问题,你可以使用 Redux 强制你以类似的方式进行,并避免管理本地状态与全局状态的混合(这通常是难以管理的事情)。

如果你做对了,没有状态的组件(即不负责管理状态,因此没有事件处理程序)都可以成为纯组件,即无状态组件,即基于 props 返回 JSX 的函数:

const SearchResults = (data) => <div>data.map( () => <etc /> )</div>

【讨论】:

谢谢!虽然,这并不是我真正想要做的。我所追求的是提供一种过滤已经处于应用程序状态的数据的方法,而不是获取数据并将其设置为基于搜索查询的应用程序状态。所以,最终,我无论如何都不会改变或改变数据,只是根据用户输入呈现数据的一个子集。也许整件事都是个坏主意,但是是的。 @joehdodd 你肯定在改变数据。过滤后的数据与原始数据不同。如果状态中已经有data,则需要额外设置filteredData,默认为[...data] @estus 好的。我想我的意思是我没有变异源数据中的数据。 /耸肩 @joehdodd 在这一点上,filteredData 是全新数据还是从 this.state.data.filter(...) 获得的现有数据的子集都没有关系,因为原始代码没有问题包含***.com/help/mcve 并且不清楚这些组件是如何使用的以及如何管理状态(data)。答案很难比问题更好。 @estus。好的。对于一个措辞不佳且构思不佳的问题,我深表歉意。这是一个真诚的问题,但我想这并不重要。我试图提供重要的内容和要解决的问题。我认为我的问题不在于如何管理数据,所以我询问了我可以使用什么来使我的组件能够在一个地方摄取一些用户输入和应用程序数据,并返回过滤后的数据基于其他地方的用户输入。道歉。下次我会做得更好,这样我的问题就会被认为值得花时间让别人回答。【参考方案2】:

您可以创建一个保存过滤器的数据存储类,将其作为属性传递给两个组件,然后让 SearchFilter 组件更改其中的值。

【讨论】:

以上是关于在没有关系的 React 组件之间共享数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 react-query useMutation 在多个组件之间共享数据

React Native 中组件之间的道具和共享数据

在项目之间共享 React 组件的最简单方法是啥? [关闭]

react js中不相关的组件之间如何共享数据?

Vue组件之间的数据共享

Vue组件之间的数据共享