我刚开始使用ReactJS,我有一个问题。
我的应用程序本质上是一个带有过滤器和更改布局的按钮的列表。 目前我正在使用三个组件:<list />, < Filters />和<TopBar />,现在显然,当我在< Filters />中更改设置时,我想在<list />中触发一些方法来更新我的视图。
我如何使这3个组件相互交互,或者我是否需要某种全局数据模型,我只需要对其进行更改?
我刚开始使用ReactJS,我有一个问题。
我的应用程序本质上是一个带有过滤器和更改布局的按钮的列表。 目前我正在使用三个组件:<list />, < Filters />和<TopBar />,现在显然,当我在< Filters />中更改设置时,我想在<list />中触发一些方法来更新我的视图。
我如何使这3个组件相互交互,或者我是否需要某种全局数据模型,我只需要对其进行更改?
当前回答
我看到这个问题已经有了答案,但如果你想了解更多细节,组件之间的通信总共有3种情况:
案例1:父到子通信 案例2:子到父通信 案例3:不相关的组件(任何组件到任何组件)通信
其他回答
如果您想探索组件之间通信的选项,并且感觉通信变得越来越困难,那么您可能会考虑采用一种好的设计模式:Flux。
它只是一组规则,定义了如何存储和更改应用程序范围内的状态,以及如何使用该状态来呈现组件。
Flux有很多实现,Facebook的官方实现就是其中之一。虽然它被认为包含了最多的样板代码,但它更容易理解,因为大部分内容都是显式的。
其他的一些替代品是flumox, flumox和redux。
我曾经是你现在的位置,作为一个初学者,你有时会觉得不适应如何反应的方式来做这件事。我将尝试用我现在思考的方式来解决这个问题。
国家是交流的基石
通常它归结于你改变这个组件的状态的方式在你的例子中你指出三个组件。
<List />:它可能会根据筛选器显示项目列表 <Filters />:筛选将更改数据的选项。 <TopBar />:选项列表。
为了协调所有这些交互你需要一个更高的组件我们叫它App,它会把动作和数据传递给每个组件例如,它看起来是这样的
<div>
<List items={this.state.filteredItems}/>
<Filter filter={this.state.filter} setFilter={setFilter}/>
</div>
因此,当setFilter被调用时,它将影响filteredItem并重新渲染两个组件;。如果这不是完全清楚,我给你一个例子,你可以在一个文件中检查复选框:
import React, {Component} from 'react';
import {render} from 'react-dom';
const Person = ({person, setForDelete}) => (
<div>
<input type="checkbox" name="person" checked={person.checked} onChange={setForDelete.bind(this, person)} />
{person.name}
</div>
);
class PeopleList extends Component {
render() {
return(
<div>
{this.props.people.map((person, i) => {
return <Person key={i} person={person} setForDelete={this.props.setForDelete} />;
})}
<div onClick={this.props.deleteRecords}>Delete Selected Records</div>
</div>
);
}
} // end class
class App extends React.Component {
constructor(props) {
super(props)
this.state = {people:[{id:1, name:'Cesar', checked:false},{id:2, name:'Jose', checked:false},{id:3, name:'Marbel', checked:false}]}
}
deleteRecords() {
const people = this.state.people.filter(p => !p.checked);
this.setState({people});
}
setForDelete(person) {
const checked = !person.checked;
const people = this.state.people.map((p)=>{
if(p.id === person.id)
return {name:person.name, checked};
return p;
});
this.setState({people});
}
render () {
return <PeopleList people={this.state.people} deleteRecords={this.deleteRecords.bind(this)} setForDelete={this.setForDelete.bind(this)}/>;
}
}
render(<App/>, document.getElementById('app'));
奇怪的是,没有人提到mobx。这个想法类似于redux。如果我有一段数据,多个组件订阅了它,那么我可以使用该数据来驱动多个组件。
即使他们不是父母-孩子关系,也有这样的可能性——那就是流动。有一个很好的(对我个人来说)实现称为Alt.JS(与Alt-Container)。
例如,您可以拥有依赖于组件详细信息设置的边栏。Component Sidebar与SidebarActions和SidebarStore连接,而Details是DetailsActions和DetailsStore。
你可以像那样使用AltContainer
<AltContainer stores={{
SidebarStore: SidebarStore
}}>
<Sidebar/>
</AltContainer>
{this.props.content}
这将保留商店(我可以用“商店”而不是“商店”道具)。现在,{this.props。content}可以是细节,取决于路由。假设/Details将我们重定向到那个视图。 例如,细节将有一个复选框,如果选中的话,将把侧边栏元素从X更改为Y。
从技术上讲,它们之间没有关系,没有通量是很难做到的。但这样就相当容易了。
现在让我们进入DetailsActions。我们会在那里创建
class SiteActions {
constructor() {
this.generateActions(
'setSiteComponentStore'
);
}
setSiteComponent(value) {
this.dispatch({value: value});
}
}
和DetailsStore
class SiteStore {
constructor() {
this.siteComponents = {
Prop: true
};
this.bindListeners({
setSiteComponent: SidebarActions.COMPONENT_STATUS_CHANGED
})
}
setSiteComponent(data) {
this.siteComponents.Prop = data.value;
}
}
现在,这就是魔法开始的地方。
如你所见,这里有SidebarActions的bindListener。如果使用setSiteComponent,将使用ComponentStatusChanged。
现在在SidebarActions
componentStatusChanged(value){
this.dispatch({value: value});
}
我们有这样的东西。它会在调用时分派那个对象。如果setSiteComponent in store将被使用(你可以在组件中使用例如onChange on Button或其他)它将被调用
现在在边栏商店中我们会有
constructor() {
this.structures = [];
this.bindListeners({
componentStatusChanged: SidebarActions.COMPONENT_STATUS_CHANGED
})
}
componentStatusChanged(data) {
this.waitFor(DetailsStore);
_.findWhere(this.structures[0].elem, {title: 'Example'}).enabled = data.value;
}
这里你可以看到,它会等待DetailsStore。这是什么意思?这或多或少意味着这个方法需要等待DetailsStoreto更新才能更新自己。
博士tl; 一个商店正在监听商店中的方法,并将从组件操作中触发一个操作,该操作将更新自己的商店。
我希望它能对你有所帮助。
我看到这个问题已经有了答案,但如果你想了解更多细节,组件之间的通信总共有3种情况:
案例1:父到子通信 案例2:子到父通信 案例3:不相关的组件(任何组件到任何组件)通信