通过prevState在React / JavaScript中使用Concat数组

时间:2019-04-24 17:45:48

标签: javascript arrays reactjs

这是我的实际代码:

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>
        )...

我该怎么做?我希望我的问题是可以理解的。

3 个答案:

答案 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)

  1. 您可以将其保留为空数组而不是null。您可以只使用点差运算符。
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可以为您完成这项工作。

http://underscorejs.org

http://lodash.com/docs

  1. 然后在render函数中,您可以更改三元运算符以检查长度,如果length为0(如在初始化中一样),则将执行else部分。
{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)

本来打算将此添加为评论,但是太长了。

如果我正确理解了您的问题,那么其他人已经回答了您的问题,但是,您不应该按照自己的意愿去做。

我可以告诉您,您的目标是声明性的并通过道具来处理事情,但是命令式思维的残余使事情变得复杂。据我所知,当父组件具有新通知时,它将同时传递newNotificationsisNewNotification。然后它将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>
    ) : (
      /* ... */
    )
  )
}