اپلیکیشن من شامل یک لیست با فیلتر های آن و یک button برای تغییر layout می باشد. در حال حاضر از سه کامپوننت:
- </list>
- </Filters>
- </TopBar>
استفاده می کنم. می خوام زمانی که تنظیمات در </Filters> تغییر کرد متدی در کامپوننت </list> برای بروزرسانی view اجرا شود.
چطور میتونم بین این سه کامپوننت ارتباط برقرار کنم؟ آیا باید از مدل داده global برای انجام این کار استفاده کنم؟
بهترین روش بستگی به برنامه ریزی شما برای این کامپوننت ها دارد. من دو سناریو زیر را در نظر می گیرم:
<Filters />
فرزند کامپوننت<List />
است.- هر دو کامپوننت
<Filters />
و<List />
فرزندان یک کامپوننت والد هستند.
سناریو 1:
در این سناریو شما باید یک متد اداره کننده را از </List> به </Filters> بفرستید که می تواند در رویداد onChange برای فیلتر کردن با مقدار جاری فراخوانی شود.
از این لینک می توانید نمونه کد سناریو 1 را مشاهده کنید.
var Filters = React.createClass({
handleFilterChange: function() {
var value = this.refs.filterInput.getDOMNode().value;
this.props.updateFilter(value);
},
render: function() {
return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />;
}
});
var List = React.createClass({
getInitialState: function() {
return {
listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'],
nameFilter: ''
};
},
handleFilterUpdate: function(filterValue) {
this.setState({
nameFilter: filterValue
});
},
render: function() {
var displayedItems = this.state.listItems.filter(function(item) {
var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase());
return (match !== -1);
}.bind(this));
var content;
if (displayedItems.length > 0) {
var items = displayedItems.map(function(item) {
return <li>{item}</li>;
});
content = <ul>{items}</ul>
} else {
content = <p>No items matching this filter</p>;
}
return (
<div>
<Filters updateFilter={this.handleFilterUpdate} />
<h4>Results</h4>
{content}
</div>
);
}
});
React.renderComponent(<List />, document.body);
سناریو 2:
مثل سناریو 1 یک تابع اداره کننده را باید در نظر بگیریم، با این تفاوت که یک کامپوننت والد برای هر دو ایجاد می کنیم و تابع اداره کننده را به کامپوننت </Filters> و لیست فیلتر شده را برای کامپوننت </List> ارسال می کنیم. این روش دو کامپوننت </List> و </Filter> را از هم جدا می کند و راه بهتری به نظر می رسد.
از این لینک می توانید نمونه کد سناریو 2 را مشاهده کنید.
var Filters = React.createClass({
handleFilterChange: function() {
var value = this.refs.filterInput.getDOMNode().value;
this.props.updateFilter(value);
},
render: function() {
return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />;
}
});
var List = React.createClass({
render: function() {
var content;
if (this.props.items.length > 0) {
var items = this.props.items.map(function(item) {
return <li>{item}</li>;
});
content = <ul>{items}</ul>
} else {
content = <p>No items matching this filter</p>;
}
return (
<div className="results">
<h4>Results</h4>
{content}
</div>
);
}
});
var ListContainer = React.createClass({
getInitialState: function() {
return {
listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'],
nameFilter: ''
};
},
handleFilterUpdate: function(filterValue) {
this.setState({
nameFilter: filterValue
});
},
render: function() {
var displayedItems = this.state.listItems.filter(function(item) {
var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase());
return (match !== -1);
}.bind(this));
return (
<div>
<Filters updateFilter={this.handleFilterUpdate} />
<List items={displayedItems} />
</div>
);
}
});
React.renderComponent(<ListContainer />, document.body);