У меня есть API (/js/feed/sms.json), который возвращает данные, которые выглядят так:

[
    {
        id: 1,
        name: "Test feeds 1",
        headline: "Here is a headline",
        feed-url: "/something?q=1"
    },
    {
        id: 2,
        name: "Test feeds 2",
        headline: "Here is another headline",
        feed-url: "/something?q=2"
    },
    {
        id: 3,
        name: "Test feeds 3",
        headline: "Here is a third headline",
        feed-url: "/something?q=3"
    }
]

У меня есть пара компонентов React.

Первый - это вызов API: fetch-api-data.jsx:

import * as axios from 'axios';

export default class FetchApiData {
  constructor() {
    console.log('FetchAPIData loaded');
  }
  static shareMyStoryData(URL) {
    return axios.get(URL)
    .then(function (response) {
      
    })
    .catch(function (error) {
      console.log(error);
    });
  }
}

Второй - это компонент, который анализирует данные.

import * as React from 'react';
import * as DOM from 'react-dom';
import PropTypes from 'prop-types';
import axios from 'axios';
import './share-my-story.scss';
import FetchApiData from './fetch-api-data';

class ShareMyStory extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      smsData: ''
    }
  }

  componentDidMount() {
    const URL = '/js/feed/sms.json';
    FetchApiData
      .shareMyStoryData(URL)
      .then((response) => {
        this.setState({smsData: response });
      })
      .catch((error) => {
        console.log(error);
      });
  }

  render() {
console.log(this.state.smsData);
    return (
      <div>
        <h1>{this.state.smsData.name}<h1>
        <h2>{this.state.smsData.headline}</h2>
        <h3><a href={this.state.smsData.link}>{this.state.smsData.link}</a></h3>
      </div>
    );
  }
}

ShareMyStory.propTypes = {
  name: PropTypes.string,
  headline: PropTypes.string,
  link: PropTypes.string,
  smsData: PropTypes.array
}

DOM.render(
  <ShareMyStory/>, document.getElementById('share-my-story'));

У меня 2 проблемы:

Во-первых, я получаю undefined в моем console.log this.state.smsData.

Во-вторых, мне нужно пройти через этот объект и вывести элементы в ответ. Я из Angular, поэтому я знаком с их итеративным ng-repeat, но я не вижу подобного инструмента в React. Есть ли предпочтительный способ сделать это?

0
TWLATL 29 Авг 2017 в 16:07

3 ответа

Лучший ответ

Если у вас действительно есть этот пустой .then(function(response){}) в вашем FetchApiData, то это проблема. Либо добавьте туда {return response} (бесполезно, но по крайней мере тогда это должно работать), либо удалите .then.

На ваш второй вопрос, как отмечали другие: в React вы используете метод .map массива для итерации массива:

{ this.state.smsData.map(data => <div>...</div>) }

Некоторые моменты: если ваш smsData является (или будет) массивом, то лучше инициализировать его либо undefined, либо пустым массивом. Я бы посоветовал undefined, чтобы вы могли провести различие между A) пока нет данных и B. Данные были получены, но нет записей (то есть smsData.length === 0)

Затем в своем компоненте вы можете проверить, следует ли отображать данные, индикатор загрузки или какое-либо сообщение об отсутствии записей, например:

render() {
    const { smsData } = this.state;
    if (!smsData) { return <div>Loading...</div>; }
    if (smsData) {
        if (smsData.length === 0) { return <div>No data</div>; }
        return smsData.map(data => <div>...</div>);
    }
}
1
Fozoro 28 Мар 2019 в 21:42

Если вы получаете данные, и состояние меняется, но когда вы сохраняете console.log, он возвращает неопределенное значение, это может быть потому, что функция setState не выполняется к тому времени, когда вы вызываете console.log.

Попробуйте что-то вроде этого: функция будет выполнена после завершения части setState.

this.setState({
            someSate: obj
        }, () => {
            console.log(this.state.smsData);
        });
0
39fredy 29 Авг 2017 в 14:46

1) Проверьте, какая из них регистрируется первой, возможно, ваши fetchData не завершены, когда вы запускаете render (). Вот почему вы получаете smsData по умолчанию.

2) Для того, чтобы перебрать данные, предположим, что dataArray - это массив, который вам нужно перебрать

FetchApiData
  .shareMyStoryData(URL)
  .then((response) => {
    // See if this is logging after Render is logged in
    console.log('In FetchApiData: ', this.state.smsData);
    this.setState({smsData: response });
  })

render() {
  console.log('In Render: ', this.state.smsData);

  const listItems = this.state.dataArray.map(function(item) {
    return (
      <li key="{item.name}">
        <a href="{item.link}">{item.name}</a>
      </li>
    );
  });
  return (<ul>{listItems}</ul>);
}
2
Nafiul Islam 29 Авг 2017 в 13:21