我正在尝试为具有不同布尔道具的组件集合(如DropDown菜单(实现一个过滤器。
最初,我的所有组件都被渲染,但当我对过滤器进行选择时,我希望只渲染与所做选择相关的组件。为了做到这一点,我认为我应该有一个由我的组件填充的数组和一个容器,只有当组件安装时,它才会与此方法ReactDOM(array,container)
一起使用。
问题是:如果我有一个已经渲染的组件集合,它们都是同一个父节点的子节点,有没有办法从父节点动态更新它们的道具?我想这样做是为了实现有条件的渲染,以决定渲染哪个组件。
class EventsPlanned extends Component{ //the parent
constructor(props){
super(props);
this.state={
showAllEvents: true,
showUnmappedEvents: false,
}
}
componentDidMount(){
var container = document.getElementById("eventToShowContainer");
var arr=[];
var eventsArrayJSON = localStorage.getItem("eventsArray");
var eventsArray = JSON.parse(eventsArrayJSON);
if(eventsArray.length !==0){
for(let i=0; i<eventsArray.length; i++){
arr.push(<Event key={i}
eventName={eventsArray[i].name}
eventPhoto={eventsArray[i].photo}
eventPeriods={eventsArray[i].periods}
eventDescription={eventsArray[i].description}
eventTag={eventsArray[i].tag}
eventIsDraft={this.state.showAllEvents}
eventIsMapped={this.state.showUnmappedEvents}/>);
}
ReactDOM.render(arr, container);
} else {
ReactDOM.render(this.nothingToShow(), container);
}
}
filterHandler = (item) =>{ //callback function for dropdown child
switch(item){
case "Events Planned":
this.setState({
showAllEvents: true,
showUnmappedEvents: false,
});
break;
case "Unmapped Events":
this.setState({
showAllEvents: false,
showUnmappedEvents: true,
});
break;
nothingToShow = () =>{ //in case there aren't event
return <div className="w3-container">
<div className="w3-panel">
<h1>Nessun Evento da mostrare</h1>
</div>
</div>
}
render(){
return(
<div>
<EventsHeader filterHandler={this.filterHandler}/>
<div id="eventToShowContainer"/>
</div>
);
}
}
export default EventsPlanned;
class Event extends Component{ // the child
state={
name: this.props.eventName,
photo: this.props.eventPhoto,
periods: this.props.eventPeriods,
description: this.props.eventDescription,
tag: this.props.eventTag,
isDraft: this.props.eventIsDraft,
showUnmapped: this.props.showUnmapped
}
render(){
if(this.state.showUnmapped){
return(
<div className="w3-container">
<div className="eventPanel w3-panel">
<h1>name: {this.state.name}</h1>
<h6>description: {this.state.description}</h6>
<h6>{this.state.periods[0]}</h6>
<h6>{this.state.tag[0]}</h6>
</div>
</div>
);
}
}
export default Event;
要做到这一点,首先需要在父级的render
方法中呈现所有子级。
从componentDidMount
中删除任何呈现逻辑,并直接在render
方法中呈现所有标记:
// EventsPlanned component
state = {
events: [],
showEvents: false,
showUnmappedEvents: false,
}
componentDidMount() {
const eventsArrayJSON = localStorage.getItem("eventsArray");
const events = JSON.parse(eventsArrayJSON);
if (events.length > 0) this.setState({ events })
}
filterHandler = filter => ...
nothingToShow() {
return (
<div className="w3-container">
<div className="w3-panel">
<h1>Nessun Evento da mostrare</h1>
</div>
</div>
)
}
render() {
const { events, showAllEvents, showUnmappedEvents } = this.state
return (
<div>
<EventsHeader filterHandler={this.filterHandler}/>
<div id="eventToShowContainer">
{events.map(e => (
<Event
key={e.name}
eventName={e.name}
eventPhoto={e.photo}
eventPeriods={e.periods}
eventDescription={e.description}
eventTag={e.tag}
eventIsDraft={showAllEvents}
eventIsMapped={showUnmappedEvents}
/>
))}
{events.length === 0 && this.nothingToShow()}
</div>
</div>
)
}
这样,每次父级状态更改时,子级都将获得更新的eventIsDraft
和eventIsMapped
道具,因为每次状态更改都意味着重新渲染。
你现在的做法:
初始化父级的
render
以呈现容器div->
componentDidMount
->
getElementById
以将容器->
ReactDOM.render
找到该容器`
在React中已经过时了,现在您需要忘记与命令式DOM更改相关的一切(你好,jQuery和再见!(,将其全部留在2014年,并深入到显式状态管理和声明式UI的奇妙世界中。
我提出的解决方案逻辑是下一个:
初始渲染将渲染
nothingToShow
->
componentDidMount
将setState
如果localStorage
中有任何事件->
setState
现在将触发render
->
,如果事件处于状态,render
将绘制我们的Event
组件阵列
并且,在过滤器更改的事件中:
filterHandler
调用setState
->
setState
触发render
->render
读取更新的this.state
,并使用更新的EventIsDraft
和EventIsMapped
道具呈现Event
的
由于现在Event
组件一直从父级接收实际道具,我们不需要它具有本地状态,因此它变得简单如下:
const Event = props => props.showUnmapped && (
<div className="w3-container">
<div className="eventPanel w3-panel">
<h1>name: {props.name}</h1>
<h6>description: {props.description}</h6>
<h6>{props.periods[0]}</h6>
<h6>{props.tag[0]}</h6>
</div>
</div>
)
PS:不确定你是如何区分草稿/映射事件的,因为你的代码没有清楚地反映