React-Native async Array.map = undefined не является объектом - PullRequest
0 голосов
/ 13 марта 2019

Я пытаюсь создать свое первое гибридное приложение с ReactNative. У меня проблема с моим Array.map…

class HomeScreen extends React.Component {

  state = {
    isLoading: false,
    captured: false,
    wished: false,
    exchanged: false,
    data: {}
  };

  async getPokemonFromApiAsync() {
    try {
      this.setState({isLoading: true});
      let response = await fetch('https://pokeapi.co/api/v2/pokemon/?limit=0&offset=20');
return this.setState({
        isLoading: false,
        data: await response.json()
       });
    } catch (error) {
      console.error(error);
  }

  (...)    

  componentWillMount() {
      this.getPokemonFromApiAsync()
  }

  (...)

  result = (result = this.state.data.results) => {
      console.log('test', this.state.data);
      return (
         <View>

             (...)

             result.map( (item, index) => {

             (...)

             }
         </View>
      )
  } 
}

Я не понимаю, почему моя функция getPokemonFromApiAsync пуста. Симулятор iOS возвращает ошибку TypeError: Undefined не является объектом (оценка 'result.map')

А при добавлении конструктора вроде:

constructor(props) {
   super(props)
   this.getPokemonFromApiAsync = This.getPokemonFromApiAsync.bind(this)
}

У меня в консоли много ошибок:

Предупреждение. Невозможно вызвать% s для компонента, который еще не подключен. Это не работает, но это может указывать на ошибку в вашем приложении. Вместо этого присвойте this.state напрямую или определите свойство класса state = {}; с требуемым состоянием в компоненте% s., SetState, HomeScreen

Для меня это нормально ...

Что такое хороший жизненный цикл для асинхронного запроса Http?

Ответы [ 4 ]

0 голосов
/ 13 марта 2019

Причина, по которой вы получаете ошибку TypeError: Undefined is not an object (evaluating 'result.map'), заключается в том, что вы получаете result из this.state.data.results, но поскольку данные асинхронные, при первом отображении данные имеют значение {} (потому что вы его установили в состоянии), поэтому data.result равно undefined, и вы не можете использовать .map() в неопределенном.

Чтобы решить эту проблему, вы можете проверить, не является ли data.result неопределенным, перед его рендерингом.

  return (
     <View>

         (...)

         result && result.map( (item, index) => {

         (...)

         }
     </View>
  )
0 голосов
/ 13 марта 2019

Лучшим способом является реализация значений состояния, когда ваше обещание разрешается с использованием «then».

let response = fetch('https://pokeapi.co/api/v2/pokemon/?limit=0&offset=20')
  .then((response) => {
     this.setState({
       isLoading: false,
       data: response.json()
     });
  });

Возможно, вы сможете обработать свои данные (result.map) в обратном вызове Promise и напрямую вставитьрезультат в вашем компоненте.

И, кстати, вызовы XHR обычно обрабатываются в методе componentDidMount.

0 голосов
/ 13 марта 2019

Ваша ошибка вызвана тем, как вы установили исходное значение data в состоянии.

Вы настроили его как:

state = {
  isLoading: false,
  captured: false,
  wished: false,
  exchanged: false,
  data: {} // <- here you define it as an object, with no parameters
};

Вы должны установить его как объект с параметром результатов`. Итак, ваше начальное состояние должно выглядеть как

state = {
  isLoading: false,
  captured: false,
  wished: false,
  exchanged: false,
  data: { results: [] } // <- here you should define the results inside the object
};

Причина, по которой вы получаете ошибку:

TypeError: Undefined is not an object (evaluating 'result.map')

Это потому, что при первоначальном рендеринге, до того как ваш ответ на выборку вернулся, он пытается map преодолеть this.state.data.results, которого не существует. Необходимо убедиться, что в состоянии есть начальное значение для results.

Это должно остановить первоначальную ошибку, однако вам необходимо убедиться, что то, что вы сохраняете в состояние для data, также является массивом, в противном случае вы продолжите получать ту же ошибку.


componentWillMount устарел, и вы должны использовать componentDidMount.

Кроме того, так как вы вызываете асинхронную функцию внутри себя componentWillMount, вы должны выполнить ее рефакторинг следующим образом:

async componentDidMount() {
  await this.getPokemonFromApiAsync()
}

Так что монтирование не происходит до тех пор, пока не будет завершен запрос на выборку.


Я бы также реорганизовал ваш getPokemonFromApiAsync, чтобы вы получили response.json(), прежде чем пытаться установить его в состояние. Вам также не нужен оператор return, так как this.setState ничего не возвращает.

async getPokemonFromApiAsync() {
  try {
    this.setState({isLoading: true});
    let response = await fetch('https://pokeapi.co/api/v2/pokemon/?limit=0&offset=20');
    let data = await response.json(); // get the data 
    this.setState({
      isLoading: false,
      data: data // now set it to state
    });
  } catch (error) {
    console.error(error);
}

Полдник:

Вот очень простая закуска, показывающая работающий код https://snack.expo.io/@andypandy/pokemon-fetch

Код для перекуса:

export default class App extends React.Component {

  state = {
    isLoading: false,
    captured: false,
    wished: false,
    exchanged: false,
    data: { results: [] } // <- here you should define the results inside the object
  };

  getPokemonFromApiAsync = async () => {
    try {
      this.setState({ isLoading: true });
      let response = await fetch('https://pokeapi.co/api/v2/pokemon/?limit=0&offset=20');
      let data = await response.json(); // get the data
      this.setState({
        isLoading: false,
        data: data // now set it to state
      });
    } catch (error) {
      console.error(error);
    }
  }

  async componentDidMount () {
    await this.getPokemonFromApiAsync();
  }

  render () {
    return (
      <View style={styles.container}>
        {this.state.data.results.map(item => <Text>{item.name}</Text>)}
      </View>
    );
  }
}
0 голосов
/ 13 марта 2019

Лучший способ использования библиотеки Axios Github ссылка

npm install axios

Наконец, еженедельные загрузки - это более 4 000 000+ Github Starts 50 000 +

...