Реагировать на проблему сопоставления API - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь сделать простой запрос на выборку и пытаюсь отобразить ответ для отображения на странице.

Результаты API корректно отображаются, когда я console.log (data), но после добавления функции отображения они отображаются как неопределенные.Я пробовал и data.map, и data.results.map

Я не смог найти работающее решение ни в одном другом потоке!

componentDidMount() {
    fetch("http://private-cc77e-aff.apiary-mock.com/posts")
      .then(results => results.json())
      .then(data => {
          let posts = data.results.map(post => {
          console.log(posts);
          });
      });
}

Любая помощь будет признательна!

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Мы не совсем уверены, каков ваш ответ API, но вы что-то делаете в журнале как-то неправильно.Вы присваиваете posts переменной, но пытаетесь использовать ее в методе .map.

Я предполагаю, что ваш ответ API выглядит примерно так:

{
  results: [
    { id: 1, name: "foo" },
    { id: 2, name: "bar" },
    { id: 3, name: "baz" },
  ],
};

Это данные, и так как вы назначаете data.results как сообщения, именно поэтому я предполагаю такой ответ.Я предоставляю варианты, которые вы можете попробовать.Здесь я имитирую запрос API с помощью функции, поэтому не беспокойтесь об этой части, пожалуйста.

Просто зарегистрируйте весь массив results.

const data = {
  results: [
    { id: 1, name: "foo" },
    { id: 2, name: "bar" },
    { id: 3, name: "baz" },
  ],
};

const fakeRequest = () =>
  new Promise(resolve => setTimeout(() => resolve(data), 1000));

class App extends React.Component {
  componentDidMount() {
    fakeRequest()
      .then( data => {
        console.log( data.results );
      })
  }
  render() {
    return <div>Look the console. We are logging the whole array.</div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Вы можете отобразить массив и зарегистрировать каждый элемент по одному

Поскольку мы просто хотим регистрировать элементынам не нужно использовать map здесь, достаточно forEach.

const data = {
  results: [
    { id: 1, name: "foo" },
    { id: 2, name: "bar" },
    { id: 3, name: "baz" },
  ],
};

const fakeRequest = () =>
  new Promise(resolve => setTimeout(() => resolve(data), 1000));

class App extends React.Component {
  componentDidMount() {
    fakeRequest()
      .then( data => {
        data.results.forEach( post => console.log( post) )
        // or as a shorthand
        // data.results.forEach(console.log)
      })
  }
  render() {
    return <div>Look the console. We are logging each post one by one.</div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Установите свое состояние с результатами и отобразите его в методе рендеринга

В большинстве случаев выхотеть сделать.Просто регистрации недостаточно, как мы знаем.

const data = {
  results: [
    { id: 1, name: "foo" },
    { id: 2, name: "bar" },
    { id: 3, name: "baz" },
  ],
};

const fakeRequest = () =>
  new Promise(resolve => setTimeout(() => resolve(data), 1000));

class App extends React.Component {
  state = {
    posts: [],
  }
  componentDidMount() {
    fakeRequest()
      .then( data => {
        this.setState( { posts: data.results})
      })
  }
  render() {
    if ( !this.state.posts.length ) {
      return <p>No posts yet</p>
    }
    return (
      <div>
        {
          this.state.posts.map( post =>
            <div key={post.id}>
            <p>{post.id}</p>
            <p>{post.name}</p>
            </div>
          )
        }
      </div>
      );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
0 голосов
/ 22 сентября 2018

Не уверен, какова структура ваших данных, но частью вашей проблемы является то, что вы пытаетесь зарегистрировать posts до того, как .map закончит заполнять их.

То, что вы могли бы сделать, это сохранить данные, полученные от API, в состоянии (используйте map, если вам нужно нормализовать данные), а затем выполнить рендеринг с использованием this.state.posts.

Не забудьте начать с начального значения пустого массива, и вы можете условно визуализировать сообщения или загрузчик в зависимости от длины массива.

Вот небольшой пример с кодом, похожим на ваш вариант использования:

const Joke = ({joke}) => <div style={{border: '1px solid #ccc', padding: '15px'}}>{joke}</div>

class App extends React.Component {
  // initial value (array)
  state = { jokes: [] }

  componentDidMount() {
    // get data when component monuted 
    fetch("https://api.icndb.com/jokes/random/10")
    .then(data => data.json())
    .then(result => {
      // normalize data with map
      const jokes = result.value.map(obj => obj.joke);
      // update the state for next render
      this.setState({jokes})
    })
  }

  render() {
    const { jokes } = this.state;
    return (
      <div>
        {
          // conditionally render the array or loading (if data isn;t ready yet)
          jokes.length
            ? jokes.map(joke => <Joke joke={joke} />)
            : "Loading..."
        }
      </div>
    );
  }
}

const root = document.getElementById("root");
ReactDOM.render(<App />, root);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root" />
...