我有一个组件,可以根据之前单击的项目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,
        })
      })
    }
  }

最佳答案

在您的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应该是与componentDidUpdate结合使用的getDerivedStateFromProps(这是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
        })
      })
  }
}

10-08 00:52