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

IT技术 javascript reactjs react-context
2021-05-12 23:03:28

我正在开发一个 React 组件库,它允许通过将对象数组和<input/>as 属性传递给<SearchFilter/>组件过滤客户端数据我想将过滤后的结果返回到一个单独的 <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>
    )
  )}
/>

这就是我想要实现的目标,因为我希望允许<SearchFilter/>在树中的一个位置渲染组件,并允许在其他地方<SearchResults/>渲染组件,以便在树的组成方式方面具有最大的灵活性,因此,如何视图被渲染。

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

谢谢!

2个回答

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

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

全局状态存储,例如 Redux,可以帮助您对此进行建模,但本质上它只不过是“一个”组件管理状态,其他组件根据该状态进行渲染。下层组件中的事件会触发数据的变化,这会导致状态发生变化,这会导致子组件的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>

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