【问题标题】:Concat Arrays in React/JavaScript via prevState通过 prevState 在 React/JavaScript 中连接数组
【发布时间】:2019-04-24 17:45:48
【问题描述】:

这是我的实际代码:

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"}]

prevState.newNotifications 不为空时,我想将我的prevProps.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>
        )...

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

【问题讨论】:

  • 添加的newNotification 不是作为props 的一部分传入的吗?

标签: javascript arrays reactjs


【解决方案1】:

在您的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
  }
}

【讨论】:

  • 不要认为这会削减它。您在某些时候会有重复项,因为您似乎每次更新都会连接 prevState.newNotifications 两次
  • @Sushanth--不幸的是,我们不知道足够的上下文来提供更多帮助,主要是 OP 可以使用Array.concat 进行合并。其他选项(lodash 是一个不错的选项)对于深度无重复合并会更好
  • 另外,prevState. newNotifications 将永远是一个过时的副本。
【解决方案2】:
  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);

union 或 uniq 或 uniqBy 可以为您完成这项工作。

http://underscorejs.org

http://lodash.com/docs

  1. 并且在渲染函数中,您可以更改您的三元运算符来检查长度,如果长度为 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>
        )...

【讨论】:

  • 另外,prevState. newNotifications 将永远是一个过时的副本
  • 是的,我不知道他想要达到什么目的。我相信他想合并所有通知以在某种弹出窗口中显示通知历史记录可能是?如果他提供更多上下文,我们可以尝试更好地解决它。
【解决方案3】:

我打算将此添加为评论,但它太长了。

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

我可以告诉您,您的目标是声明式的并通过道具处理事情,但是命令式思维的残余使事情变得复杂。据我所知,当父组件有新通知时,它将通过newNotificationsisNewNotification。然后它将isNewNotification 翻转回false。每当您对事物进行排序时,您都是在命令式地思考,而不是在声明式地思考。使用生命周期方法也表明您在进行命令式思考(尽管有时这是必要的)。

您实际上是在尝试使用道具复制函数调用。我认为你实际上最好公开一个 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>
    ) : (
      /* ... */
    )
  )
}

【讨论】:

    猜你喜欢
    • 2015-04-16
    • 2021-07-07
    • 1970-01-01
    • 2013-10-25
    • 2014-08-17
    • 2022-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多