【问题标题】:How to reduce duplicative calls to callback functions in componentDidUpdate如何减少对 componentDidUpdate 中回调函数的重复调用
【发布时间】:2020-06-22 18:57:42
【问题描述】:

我对 React 和 Firebase 比较陌生。我阅读了几篇关于处理返回承诺或接受回调的异步函数是多么麻烦的文章,而且我知道的最终输出“正确”显示的方法很少。我正在为我的项目处理许多异步方法。据我所知,进行异步调用和放置事件侦听器的最佳位置是componentDidMountcomponentDidUpdate,因此我有一个非常轻量级的构造函数、渲染方法,并尝试将我的大部分异步调用压缩为并将我的实时数据库监听器放在那里。目前这些是我编写componentDidMountcomponentDidUpdate 代码的sn-ps。

 async componentDidMount() {

    console.log("Component did mount happen");

    const channels_value = await f1();
    const change_object = {};
    change_object[MESSENGER_CHANNELS] = channels_value;



    if (this.state[MESSENGER_ACTIVE_CHANNEL_ID]) {
      const channel_data = await f2();
      const members_value = channel_data["ids"];
      const channel_title_value = channel_data["name"];


      change_object["ids"] = members_value;
      change_object["name"] = channel_title_value;

      //Listener for upcoming messages

      realtime_db.ref(`${MESSAGES_REALTIME_REFERENCE}/${this.state[MESSENGER_ACTIVE_CHANNEL_ID]}`)
        .orderByChild(MESSAGE_CREATE_TIMESTAMP)
        .on("value", (snapshot) => {
          const messages = [];
          snapshot.forEach((snap) => {
            const obj = snap.val();
            obj[MESSAGE_ID] = snap.key;
            messages.push(obj);
          });

          const new_state = {};
          new_state[MESSENGER_MESSAGES] = messages;
          console.log("New state");
          console.log(new_state);
          this.setState(new_state);

        });
    }

    this.setState(change_object);

    //some event listeners that should persist until destroyed
  }



  async componentDidUpdate() {
    //Allows reloading
    console.log("ComponentDidUpdate occurred");

    const change_object = {};

    let boolean_one = false;
    let boolean_two = false;
    let boolean_three = false;


    if (this.state[CHANNEL_ID]) {
      const channel_data = await f2();
      const members_value = channel_data["ids"];
      const channel_title_value = channel_data["name"];



      change_object["ids"] = members_value;
      change_object["name"] = channel_title_value;

      //Listener for upcoming messages

      await realtime_db.ref(`${MESSAGES_REALTIME_REFERENCE}/${this.state[MESSENGER_ACTIVE_CHANNEL_ID]}`)
        .orderByChild(MESSAGE_CREATE_TIMESTAMP)
        .on("value", (snapshot) => {
          //Currently handling all setState logic inside the callback function to output correctly

          const messages = [];
          snapshot.forEach((snap) => {
            const obj = snap.val();
            obj[MESSAGE_ID] = snap.key;
            messages.push(obj);
          });

          //some code for deciding whether to set state
          const deciding_boolean = boolean_three || boolean_one && boolean_two;

          if (deciding_boolean) {
            this.setState(change_object);
          }
        });
    }

  }

从一些 console.logs 中,每当我执行 handleSend 导致 setState 时,重新渲染并随后再次导致 componentDidUpdatesetState,重新渲染并第二次转到 componentDidUpdate并拒绝新的更新,直到此循环再次发生。

即使它现在正确显示,componentDidUpdate 也被点击了两次,而且我总是两次获取我的数据库查询和回调,这可能会给我带来额外的运行成本,而我不知道。我想知道是否有更好的编码实践来减少这种代码重复以及成本因素。

【问题讨论】:

    标签: reactjs firebase callback event-handling react-lifecycle


    【解决方案1】:

    如果您查看react docs,您将看到componentDidUpdate 具有prevPropsprevStatesnapshot 作为参数。

    使用该信息,避免componentDidUpdate 上的无限循环和召回的最常见方法是比较prevState 是否与this.state(或您正在监视的某些特定状态)不同。你也可以比较道具,虽然这不是你的情况。

    你可以这样写:

    componentDidUpdate(prevProps, prevState) {
      \\ you can specify which part of state you want to check
      if (prevState === this.state) return
      \\ code to run
    }
    

    或将代码包装在 if 语句中:

    componentDidUpdate(prevProps, prevState) {
      if (prevState !== this.state) {
        \\ code to run
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 2017-10-19
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      相关资源
      最近更新 更多