这是我的实际代码:
class Notifications extends React.Component {
constructor(props) {
super(props);
this.state = {
newNotifications: null, //this always must be a null in constructor.
};
}
componentDidUpdate(prevProps, prevState) {
if (this.props.isNewNotification !== prevProps.isNewNotification) {
this.setState({
newNotifications: prevProps.newNotifications,
});
}
}
...
我的prevProps.newNotifications是一个数组,例如:
[{"date_time":"Wednesday, 19:42","amount_money":"2,10 USD","sender_name":"John Polaszek"}]
当prevProps.newNotifications
不为null时,我想将prevState.newNotifications
中的prevState.newNotifications
合并数组。在render()
中,我有以下方法:
{newNotifications ? (
<div className="no-test">
{newNotifications.map((newNotification, id) => (
<Fragment>
<span>
{newNotification.sender_name}
</span>
<span className="notification_amount">
{newNotification.amount_money}
</span>
</span>
<br />
<span>
{newNotification.date_time}
</span>
</Fragment>
))}
</div>
)...
我该怎么做?我希望我的问题是可以理解的。
答案 0 :(得分:0)
在您的componentDidUpdate
方法中,您有一个正确的想法,您只需要根据条件设置或设置Array.concat()。
componentDidUpdate(prevProps, prevState) {
if (this.props.isNewNotification !== prevProps.isNewNotification) {
let newNotifications;
if (prevState.newNotifications !== null) {
newNotifications = prevState.newNotifications.concat(prevProps.newNotifications);
} else {
// otherwise, set newNotifications to your other condition
}
this.setState({ newNotifications }); // computed property since the var is the same as the state name
}
}
答案 1 :(得分:0)
class Notifications extends React.Component {
constructor(props) {
super(props);
this.state = {
newNotifications: [], // maintain it as an array instead.
};
}
componentDidUpdate(prevProps, prevState) {
if (this.props.isNewNotification !== prevProps.isNewNotification) {
const newNotifications = [...prevState.newNotifications, ...prevProps.newNotifications];
this.setState({
newNotifications,
});
}
}
这不会删除重复项,您可以尝试使用下划线或lodash或自己编写函数将其删除。
union(prevProps.newNotifications, prevState.newNotifications);
工会,uniq或uniqBy可以为您完成这项工作。
{newNotifications.length ? (
<div className="no-test">
{newNotifications.map((newNotification, id) => (
<Fragment>
<span>
{newNotification.sender_name}
</span>
<span className="notification_amount">
{newNotification.amount_money}
</span>
</span>
<br />
<span>
{newNotification.date_time}
</span>
</Fragment>
))}
</div>
)...
答案 2 :(得分:0)
本来打算将此添加为评论,但是太长了。
如果我正确理解了您的问题,那么其他人已经回答了您的问题,但是,您不应该按照自己的意愿去做。
我可以告诉您,您的目标是声明性的并通过道具来处理事情,但是命令式思维的残余使事情变得复杂。据我所知,当父组件具有新通知时,它将同时传递newNotifications
和isNewNotification
。然后它将isNewNotification
翻转回false
。每当您按顺序进行操作时,就必须进行命令式思考,而不是声明式思考。达到生命周期方法也表明您必须进行认真的思考(尽管有时这是必要的)。
您实际上是在尝试使用props复制函数调用。我认为您最好公开一个addNotifications
方法,向组件获取一个ref
并调用该方法,而不是使用这种声明式但真正需要的api。
但是,实际上,我们不想公开一个命令式的api,以便组件进行通信。如果父母负责添加新的通知,则维护通知列表的位置可能更好。我猜这些通知是来自api或websocket。收到通知后,这里就是合并新通知并将其存储回父状态的地方。然后,孩子可以成为无状态组件。
class NotificationParent extends React.Component {
constructor(props) {
super(props);
this.state = {
notifications: null
};
}
componentDidMount() {
api.on("notifications", newNotifications => {
this.setState(({ notifications } => {
if (!notifications) {
return {
notifications: newNotifications
};
} else {
return {
notifications: notifications.concat(newNotifications)
};
}
});
})
}
render() {
return (
<Notifications notifications={this.state.notifications}/>
);
}
}
function Notification({ notifications }) {
return (
newNotifications ? (
<div className="no-test">
{newNotifications.map((newNotification, id) => (
<Fragment>
<span>
{newNotification.sender_name}
</span>
<span className="notification_amount">
{newNotification.amount_money}
</span>
<br />
<span>
{newNotification.date_time}
</span>
</Fragment>
))}
</div>
) : (
/* ... */
)
)
}