我有三个组成部分。
父母通过redux状态获取数据:
const mappedEvents =
events.length === 0 ? (
<p style={{ textAlign: 'center' }}>Det finns inte några händelser</p>
) : (
events.reverse().map((event, i) => {
var driver = event.driver ? keyedDrivers[event.driver] : false
var carrier = driver ? keyedCarriers[driver.carrier] : false
var customer = event.customer ? keyedCustomers[event.customer] : false
return (
<div>
<EventItem // This is a list item
key={i}
event={event}
customer={customer}
carrier={carrier}
driver={driver}
lock={keyedLocks[event.unit] || { address: {} }}
/>
</div>
)
})
)
然后在return
内部,我将其显示为:
<Grid>{mappedEvents}</Grid>
这给了我一个清单,
但我希望能够过滤它。所以我创建了一个过滤器组件,它也可以通过redux状态获取它的数据。
constructor(props) {
super(props)
this.state = {
filteredEvents: ''
}
}
toggle(event) {
this.setState({ filteredEvents: event.target.value })
}
...
const organizationList = carriers
.filter(
carrier =>
!this.state.filteredEvents ||
carrier.organization.indexOf(this.state.filteredEvents) >= 0
)
.map(carrier => (
<div>
<input
type="checkbox"
value={carrier.organization}
onChange={this.toggle.bind(this)}
/>
<MenuItem eventKey={carrier.id} key={carrier.id}>
{carrier.organization}
</MenuItem>
</div>
))
这会呈现用户可以检查的内容列表:
然而,当我点击其中一个复选框时,它开始过滤复选框数组:
所以我想知道如何传递过滤器组件,以便我可以开始过滤EventItem
数组。我是否应该开始制作一个进行过滤的reducer,或者过滤器组件是否应该将回调调用回父级,而parent会呈现过滤后的列表吗?
答案 0 :(得分:1)
基本上,您希望将过滤器状态保留在redux存储中。您的过滤器应该调度更新状态的操作,然后在渲染列表时,您将在那里过滤它。
events.filter((event) => {
// filter based on redux state
}).reverse().map((event, i) => {
-
toggle(event) {
// this.setState({ filteredEvents: event.target.value })
// dispatch an action that updates the redux state filters here
}
多一点信息
我可能会将过滤器存储为布尔值。 Reducer初始状态看起来像这样(或者你可以为事件/过滤器设置单独的reducer):
events: [],
filters: {
qlocx: false,
best: false,
bring: false // etc..
}
更新过滤器操作将设置与复选框对应的过滤器布尔值。
在您的mapStateToProps
中,您将同时拥有events
和filters
然后在渲染功能中,您可以使用.filter
根据过滤器状态过滤事件。
您可以使用类似重新选择的内容来缓存已过滤的列表,但如果只有一个小列表,则您不应该从单个过滤器功能中看到任何性能问题。
// inside the render function, filter the array based on filters set
// just a simple render function example for demonstration
render() {
return (
<div>
{events
.filter((event) => {
// filter based on redux state
if (event.qlocx && filters.qlocx) {
return true;
}
// etc..
// filter any that don't match (might want to return true if no filters are set)
return false;
})
.reverse()
.map((event, i) => {
<强>演示强>
这是一个小型演示,但没有redux。它使用setState作为已调度操作的替代,并将状态向下传递为道具,而不是使用mapStateToProps
:
class Filters extends React.Component {
onUpdateFilter = (event) => {
// event.target is the input that you changed, so you can get the name and checked properties
this.props.updateFilters(event.target.name, event.target.checked);
}
render() {
const {
filters
} = this.props;
return (
<div>
<input type="checkbox" name="one" onChange={this.onUpdateFilter} value={filters.one} />
<input type="checkbox" name="two" onChange={this.onUpdateFilter} value={filters.two} />
<input type="checkbox" name="three" onChange={this.onUpdateFilter} value={filters.three} />
</div>
);
}
}
class List extends React.Component {
// this would be your reducer's `initialState`
state = {
filters: {}
};
// this code would be in your reducer, and you'd just dispatch an action here
updateFilters = (name, value) => {
this.setState({
filters: {
// this just makes a copy of state.filters and sets state.filters[name] = value
...this.state.filters,
[name]: value
}
});
}
render() {
// both filters and items would come from mapStateToProps
const {filters} = this.state;
const {items} = this.props;
return (
<div>
<pre>filters = {JSON.stringify(filters)}</pre>
<Filters
filters={filters}
updateFilters={this.updateFilters}
/>
<ul>
{this.props.items
.filter((item) => {
if (filters.one && !item.one) {
return false;
}
if (filters.two && !item.two) {
return false;
}
if (filters.three && !item.three) {
return false;
}
return true;
})
.map((item) => (
<li key={item.name}>{item.name}</li>
))
}
</ul>
</div>
);
}
}
// this list would come from your reducer via mapStateToProps
const listItems = [
{name: 'Item 1', one: true},
{name: 'Another item 1', one: true},
{name: 'Item 2', two: true},
{name: 'Item 2,1', one: true, two: true},
{name: 'Item 2,3', two: true, three: true},
{name: 'Item 3', three: true}
];
ReactDOM.render(
<List items={listItems} />,
document.getElementById('app')
);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="app"></div>
&#13;