Реагировать на потерю данных - PullRequest
0 голосов
/ 30 апреля 2018

У меня есть компонент, в котором я получаю данные на основе идентификатора элемента, который был нажат ранее. Выборка успешна, и 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 прекрасно работает при рендеринге, но {this.state.matchData} и {this.state.testTeam} из componentDidUpdate пусты.

Может ли быть проблема в том, что 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,
        })
      })
    }
  }

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

вместо использования componentDidUpdate () ловушки жизненного цикла реакции, попробуйте использовать getDerivedStateFromProps () функцию жизненного цикла, если вы используете реагировать 16,3 , иначе попробуйте использовать componentWillReceiveProps () ниже версии . На мой взгляд, старайтесь избегать использования componentDidUpdate ().

Плюс ошибка, которую вы получаете, потому что вызвана функция setState (), когда ваш компонент каким-то образом отключается, для этого может быть несколько причин, наиболее заметное из которых -

  1. проверьте функцию рендеринга этого компонента, отправляете ли вы null или что-то еще, основываясь на определенном условии?

  2. проверьте родительский код компонента и посмотрите, когда компонент отключается.

Или вы можете поделиться этим кодом, чтобы мы могли помочь вам в этом.

Плюс попробуйте отладить с помощью ComponentWillUnmount () , поместите в него console.log () и протестируйте его для большей ясности.

Надеюсь, это поможет, спасибо

0 голосов
/ 30 апреля 2018

В вашем 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
        })
      })
  }
}
...