我正在尝试为具有不同布尔属性的一组组件(例如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;
答案 0 :(得分:1)
为此,首先,您需要使用父级的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和Bye!),将其保留在2014年,并深入了解显式状态管理和声明性UI的美好世界
接下来是我提出的解决方案逻辑:
如果
nothingToShow
->
componentDidMount
中有任何事件,则初始渲染将渲染setState
localStorage
->
将setState
现在触发render
->
,如果事件处于状态,则render
将绘制我们的Event
组件数组
而且,在发生过滤器更换事件时:
filterHandler
调用setState
->
setState
触发render
->render
读取更新的this.state
并呈现{{1} }带有更新的Event
和EventIsDraft
道具
因为现在EventIsMapped
组件一直都在从父级接收实际的道具,所以我们不需要它具有局部状态,因此它变得简单:
Event
PS:由于您的代码无法清楚地反映出事件,因此不确定如何分隔草稿/映射事件