在没有关系的 React 组件之间共享数据? [英] Share data between React components with no relation?

查看:44
本文介绍了在没有关系的 React 组件之间共享数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

))}/>

这是我想要实现的,因为我希望允许在树中的一个位置呈现 <SearchFilter/> 组件,并允许 <SearchResults/> 要在其他地方呈现的组件,以便在如何组合树以及如何呈现视图方面具有最大的灵活性.

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

谢谢!

解决方案

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

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

全局状态存储,例如 Redux,可以帮助您对此进行建模,但本质上它只不过是一个"组件管理状态,以及根据该状态呈现的其他组件.下层组件中的事件会触发数据的变化,这会导致状态发生变化,从而导致子组件的道具发生变化,进而导致重新渲染.

我建议您尝试使用这种简单的模式:

class 搜索 ... {状态 = {数据:[],文本:"}使成为() {返回 (<div><搜索过滤器数据={this.state.data}onSearch={() =>this.fetchNewData()}onChange={(e) =>this.setState({text: e.targetElement.value})}文本={this.state.text}/><SearchResults data={this.state.data}/>

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

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

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

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

I'm working on a React component library that allows for client-side data filtering by passing an array of objects and an <input/> as props to a <SearchFilter/> component. I want to return the filtered results to a separate <SearchResults/> component that can be rendered elsewhere in the tree (i.e. the results component doesn't have to be a child of the input component).

I've got the filtering figured out, but I'm not sure the best route to take in React on getting the filtered data to the <SearchResults/> component.

This is what I'd like to end up with...

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

Then, using Render Props to return the data and map over that to return JSX, there would be the results component. Something like this...

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

This is what I'd like to achieve because I want to allow for rendering the <SearchFilter/> component at one place in the tree, and allow the <SearchResults/> component to be rendered elsewhere, so that there's maximum flexibility in how the tree is composed and, therefore, how the view is rendered.

I've looked into the Context API, but it seems like that would require a handful more components to be a part of my library, which further complicates what I'm trying to achieve. If that's the only way around it, then that's fine, but I wanted to ask and see if anyone can think of another solution.

Thanks!

解决方案

The bigger issue is that you will need to manage a state that is shared between components on a higher level, i.e., any component that will wrap these other two components, ultimately. With plain React, this state would be managed by the parent (or ancestor) component, passing down the relevant values as props. This opposed to the, usually bad, idea to have sibling components influence each other's state, since you well get into the "who's boss here"-problem.

The thing the Context API handles is not having to pass down props for things that typically don't change (or: typically shouldn't cause renders to trigger often).

A global state store, such as Redux, can help you modelling this, but in essence it's not much more than 'a' component managing state, and other components rendering according to that state. Events within the lower components trigger changes in the data, which will cause the state to change, which will cause the props of the children to change, which then will cause re-renders.

I'd advise you to try using this simple pattern:

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

Something along these lines. If you have trouble modelling stuff like this, you can use Redux to force you to do it in a similar way, and avoid managing local state intermixing with global state (which is typically something that is hard to manage).

If you do this right, components that have no state (i.e., aren't responsible for managing state and thus have no event handlers) can all become pure components, i.e. stateless components, i.e. functions that return JSX based on props:

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

这篇关于在没有关系的 React 组件之间共享数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆