【问题标题】:ComponentDidUpdate() data from the api with new data来自 api 的 ComponentDidUpdate() 数据和新数据
【发布时间】:2019-06-27 21:53:25
【问题描述】:

作为新手,我看到了一个类似的例子,但没有清楚地解释它们,我不明白如何解决这个问题。我有一个 API,新数据发布到 API。 ComponentDidMount() 将首次从 API 发起数据。 我浏览了文档,发现如果添加了新数据,componentDiUpdate() 将始终重新呈现页面。

这是我目前的代码:

constructor(props){
  super(props);
  this.state = {
    newData: [],
    dataApi: this.props.getAllData() //method that is using GET_ALL_DATA actions/reducers using fetch(get)
  }
}
// it gets the data
componentDidMount() {
  this.state.dataApi
}

componentDidUpdate(prevProps, prevState){
  this.state.dataApi.then(data => {
    if(prevProps.data != this.props.data) {
      this.setState({newData: data});
    }
  }
}

ComponentDidUpdate() 错误:

无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请在 componentWillUnmount 方法中取消所有订阅和异步任务。

我该如何解决这个问题?通过在有人发出发布请求时从 API 获取新数据?谢谢

【问题讨论】:

  • 听起来就像当您离开浏览器页面时,您的组件在卸载组件后仍在尝试设置状态。
  • @JohnRuddell 我认为我的做法是错误的,因为代码不起作用,我无法通过调用 this.state.dataApi 从 api 获取更新的数据
  • 是的,你不应该对你的状态做出这样的承诺,只需在 didMount 中调用getAllData() 并将.then 也链接到那里。但是如果这个组件绑定到一个网页,你需要记住,如果组件卸载,你需要在你的 Promise 中终止 setstate 调用然后回调

标签: javascript reactjs


【解决方案1】:

问题已解决,谢谢大家: 问题的解决方案是:

this.state = {
   allData: [],
   isSubmitted: false
}

async componentDidUpdate(prevProps, prevState){
  if(this.mounted && this.state.isSubmitted){
     const allData = await this.props.getAllData();
     this.setState({isSubmitted: false,
                  allData: allData.data })
  }

componentDidMount(){ 
   this.mounted=true
}

componentWillUnmount() {
   this.mounted = false; 
}

functionAddDataToApi(){
   // some logic
   this.setState({isSubmitted: true})
}

【讨论】:

    【解决方案2】:

    componentDidMount() 生命周期方法仅在您的组件第一次渲染时被调用一次。

    在您的constructor() 中,您无需对您的状态做出承诺。相反,您可以删除 dataApi 并直接调用该方法。在componentDidMount() 中,您将进行 API 调用。当 API 调用完成后,您可以使用this.setState()

    componentDidUpdate 方法会在每次更新您的 prop 或 state 值时调用。因此,更新其中的状态是个坏主意,因为您有无限循环的风险。

    constructor(props){
          super(props);
          this.state = {
               newData: [], 
          };
    }
    
    // it gets the data
    componentDidMount() {
        this.props.getAllData().then(data => {
            this.setState({
                newData: data,
             });
        });
    }
    

    【讨论】:

    • ComponentDidMount() 正在工作,我仍在尝试了解如何使用 componentDidUpdate(,一个简短的示例:让我先从表中的 api 获取所有数据,添加新记录(发布请求)记录在api中,现在不使用componentDidUpdate我必须刷新窗口才能看到表中的记录,如何在不刷新窗口的情况下解决这个问题?
    • 或者John,这个问题还没有解决,能不能帮帮我,谢谢。
    【解决方案3】:

    如果您想在重新渲染之前挂钩道具更改,请尝试挂钩到 componentWillReceiveProps。 componentWillReceiveProps 会同步更新状态。

    还有 .. 你的 componentDidMount 中的代码什么也不做 :)

    // it gets the data
    componentDidMount(){
          this.state.dataApi}
    

    尝试将其替换为

    // it gets the data
    componentDidMount() {
        this.state.dataApi.then(data => {
            this.setState({
                newData: data,
             });
        });
    }
    

    【讨论】:

      【解决方案4】:

      当异步设置状态时(例如,在一个 promise 被解决之后),重要的是确保你的组件仍然被挂载,否则,你可能会在一个未挂载的组件上设置状态(这会触发您遇到的错误)。

      为此,您需要设置某种标志(如以下示例中的this.mounted):

      componentDidMount() {
        this.mounted = true;
      }
      
      async componentDidUpdate() {
        const data = await someAPICall();
        if (this.mounted && !_.isEqual(this.state.data, data)) { // See comment below
          this.setState({data});
        }
      }
      
      componentWillUnmount() {
        this.mounted = false;
      }
      

      另外,在将旧数据与新数据进行比较时,您需要执行深度比较(在上面的示例中,我使用的是 lodash isEqual(...))。

      浅比较(即this.state.data !== data)比较每个对象的引用,无论实际数据如何,这些引用总是不同的,因此会遇到无限循环因为setState()会触发另一个componentDidUpdate()等等。

      【讨论】:

      • 做你的例子我得到无限循环。
      • 是的,如果您使用componentDidUpdate() 来更新状态,则需要某种条件,否则它将进入无限循环。请参阅我的更新答案。
      • 通过编写相同的代码,仍然会进入无限循环。应该是this.props.data?而不是 this.state.data?
      • 请阅读我在帖子中的最后一条评论,您必须进行深度比较
      • await someApiCall() (派发任何 Promiseany) this.state.data 它返回一个已解决的承诺,该承诺具有 promiseValue 对象:数据 [] 类型:获取所有数据
      猜你喜欢
      • 2019-06-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2015-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多