从父节点更新子节点的道具



我正在尝试为具有不同布尔道具的组件集合(如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>
)
}

这样,每次父级状态更改时,子级都将获得更新的eventIsDrafteventIsMapped道具,因为每次状态更改都意味着重新渲染。


你现在的做法:

初始化父级的render以呈现容器div->componentDidMount->getElementById以将容器->ReactDOM.render找到该容器`

在React中已经过时了,现在您需要忘记与命令式DOM更改相关的一切(你好,jQuery和再见!(,将其全部留在2014年,并深入到显式状态管理和声明式UI的奇妙世界中。

我提出的解决方案逻辑是下一个:

初始渲染将渲染nothingToShow->componentDidMountsetState如果localStorage中有任何事件->setState现在将触发render->,如果事件处于状态,render将绘制我们的Event组件阵列

并且,在过滤器更改的事件中:

filterHandler调用setState->setState触发render->render读取更新的this.state,并使用更新的EventIsDraftEventIsMapped道具呈现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:不确定你是如何区分草稿/映射事件的,因为你的代码没有清楚地反映

最新更新