React 获取数据丢失

Posted

技术标签:

【中文标题】React 获取数据丢失【英文标题】:React fetch data getting lost 【发布时间】:2018-10-10 16:36:42 【问题描述】:

我有一个组件,我在其中根据之前单击的项目 ID 获取数据。获取成功,console.log 显示正确的数据,但数据因 this.setState 丢失。我在同一个组件中有 componentDidUpdate 和 componentDidMount,不确定这是否可以,或者这两个可能会互相混淆?

代码如下:

const teamAPI = 'http://localhost:8080/api/teams/'
const playerAPI = 'http://localhost:8080/api/playersByTeam/'
const matchAPI = 'http://localhost:8080/api/match/'

class View extends Component 

  constructor() 
    super();
    this.state = 
      data: [],
      playersData: [],
      update: [],
      team1: [],
      team2: [],
      matchData: [],
      testTeam: [],
    ;
  

  componentDidUpdate(prevProps) 
    if (prevProps.matchId !== this.props.matchId) 
      fetch(matchAPI + this.props.matchId)
      .then((matchResponse) => matchResponse.json())
      .then((matchfindresponse) => 
        console.log(matchfindresponse);
        this.setState(
          matchData:matchfindresponse,
          testTeam:matchfindresponse.team1.name,
        )
      )
    
  

  componentDidMount() 
    fetch(teamAPI)
    .then((Response) => Response.json())
    .then((findresponse) => 
      console.log(findresponse)
      this.setState(
        data:findresponse,
        team1:findresponse[0].name,
        team2:findresponse[1].name,
      )
    )

    fetch(playerAPI + 82)
    .then(playerResponse => playerResponse.json())
    .then(players => 
      console.log(players)
      this.setState(
        playersData:players
      )
    )
  

第一次渲染也给出了这个警告:

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

Please check the code for the View component.

ComponentDidMount 中的所有内容在渲染中都可以正常工作,但 componentDidUpdate 中的 this.state.matchData 和 this.state.testTeam 为空。

问题可能是 ComponentDidMount 重新渲染了导致 ComponentDidUpdate 中的数据丢失的组件,如果是这样,我该如何解决这个问题?

像这样尝试过 ComponentWillReceiveProps 但仍然没有运气

  componentWillReceiveProps(newProps) 
    if (newProps.matchId !== this.props.matchId) 
      fetch(matchAPI + newProps.matchId)
      .then((matchResponse) => matchResponse.json())
      .then((matchfindresponse) => 
        console.log(matchfindresponse.team1.name);
        console.log(this.props.matchId + ' ' + newProps.matchId);
        this.setState(
          matchData:matchfindresponse.team1.name,
        )
      )
    
  

【问题讨论】:

:o 抱歉,也许我使用的 React 版本太旧了...上次我使用它时,我很确定我必须像那样合并!删除它,再次抱歉...我要深入了解一下! 看起来你应该使用componentWillReceiveProps而不是componentDidUpdate 【参考方案1】:

在您的 componentDidMount 上,您应该使用 Promise.all。这不是你的问题,但它确实更有意义。

componentDidMount() 
  const promises = [
    fetch(teamAPI).then(resp => resp.json()),
    fetch(playerAPI + 82).then(resp => resp.json())
  ];
  Promise.all(promises).then(([teamData, playerData]) => 
   // you can use this.setState once here
  );

看起来您的 componentDidUpdate 应该是 getDerivedStateFromProps 与 componentDidUpdate 的组合(这是对 16.3 的反应,因此如果您使用的是旧版本,请使用已折旧的 componentWillReceiveProps)。请参阅https://github.com/reactjs/rfcs/issues/26。还要注意,现在 componentDidUpdate 从 getDerivedStateFromProps 接收第三个参数。详情请见https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html

编辑:只是为了添加更多细节。 您的状态对象应该只包含其他键,例如 matchIdChanged。 那么

// in your state in your constructor add matchId and matchIdChanged then
static getDerivedStateFromProps(nextProps, prevState) 
 if (nextProps.matchId !== prevState.matchId) 
   return  matchIdChanged: true, matchId: nextProps.matchId 
 
 return null;


componentDidUpdate() 
  if (this.state.matchIdChanged) 
    fetch(matchAPI + this.props.matchId)
      .then((matchResponse) => matchResponse.json())
      .then((matchfindresponse) => 
        console.log(matchfindresponse);
        this.setState(
          matchData:matchfindresponse,
          testTeam:matchfindresponse.team1.name,
          matchIdChanged: false // add this
        )
      )
  

【讨论】:

我试过 ComponentWillReceiveProps 但结果是一样的。不过,我可能做错了什么。查看原始帖子更新以了解我做了什么。 不幸的是,我使用的是 React 16.2 版,所以我正在尝试使用 ComponentWillReceiveProps 来解决这个问题,但非常感谢您的指点。 您可以选择升级到 React 16.3。没有重大更改,而且您获得了新的上下文 API,非常好用。 我更新到 16.3 并尝试了 getDerivedStateFromProps 并立即收到此警告:警告:查看:getDerivedStateFromProps() 被定义为实例方法,将被忽略。相反,将其声明为静态方法。 只要把 static 放在它前面。我会更新答案。【参考方案2】:

如果您正在使用 react 16.3,请尝试使用 getDerivedStateFromProps() 生命周期函数,而不是使用 react 的 componentDidUpdate() 生命周期钩子,否则请尝试使用 componentWillReceiveProps()对于以下版本。在我看来,尽量避免使用 componentDidUpdate()。

您遇到的另外错误是因为调用了 setState() 函数,当您的组件以某种方式被卸载时,可能有多种原因,最突出的是 -

    检查这个组件的render函数,你是根据一定的条件发送null还是什么?

    查看组件的父代码,看看组件什么时候卸载。

或者您可以共享这些代码,以便我们可以帮助您。

另外尝试使用 ComponentWillUnmount() 进行调试,将 console.log() 放入其中并进行测试以提高清晰度。

希望对你有帮助,谢谢

【讨论】:

以上是关于React 获取数据丢失的主要内容,如果未能解决你的问题,请参考以下文章

React Native - 使用 react-navigation 和 react-redux 在屏幕之间切换时数据丢失

react antd Form 切换Table分页后Table内Input数据丢失问题处理

如何更新详细信息表中的数据并且不丢失范围选择和过滤器?

React s-s-r路由器-导航到子路由时的redux状态丢失

连接蓝牙模块后丢失数据

前端获取Long类型精度丢失解决办法