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

时间:2018-09-04 20:07:23

标签: javascript reactjs react-context

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

我已经确定了过滤条件,但是我不确定将React过滤到<SearchResults/>组件中的最佳途径。

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

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

然后,使用渲染道具返回数据并将其映射为返回JSX,将得到结果组件。像这样...

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

这是我要实现的,因为我想允许在树的某个位置渲染<SearchFilter/>组件,并允许渲染<SearchResults/>组件 elsewhere < / em>,以便在树的构成以及视图的呈现方式上具有最大的灵活性。

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

谢谢!

2 个答案:

答案 0 :(得分:1)

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

Context API处理的事情不必为通常不变的事情(或:通常不应导致渲染频繁触发)传递道具。

全局状态存储(例如Redux)可以帮助您对此建模,但从本质上讲,它不过是管理状态的“ a”组件以及根据该状态呈现的其他组件。下部组件中的事件触发数据更改,这将导致状态更改,这将导致子项的道具更改,然后导致重新渲染。

我建议您尝试使用以下简单模式:

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>

答案 1 :(得分:0)

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