React-Native async Array.map = undefined не является объектом

Я пытаюсь создать свое первое гибридное приложение с 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.info('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-запроса?

Скиньте Ждите в состояние и будет вам счастье.

squeekyDave 13.03.2019 11:58

Спасибо. Но у меня такая же ошибка. console.info('test', this.state.data) возвращает объект {}. Моя проблема заключается в том, что данные извлекаются, но не извлекаются в состоянии.

Reuno92 13.03.2019 12:18

Что ж, вам не хватает объекта конфигурации в вашем операторе выборки. убедитесь, что вы предоставили их. Я подозреваю, что ваша выборка не удалась.

squeekyDave 13.03.2019 12:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
1 610
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Лучший способ использовать библиотеку axios github связь

npm install axios

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

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

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.

Ответ принят как подходящий

Ваша ошибка вызвана тем, как вы настроили свой начальный 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>
    );
  }
}

Привет гость из будущего, для получения дополнительной информации: facebook.github.io/react-native/docs/network#using-fetch

Reuno92 29.03.2019 17:16

Причина, по которой вы получаете сообщение об ошибке 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>
  )

Другие вопросы по теме