React API映射问题

时间:2018-09-22 13:58:57

标签: reactjs mapping fetch

我正在尝试提出一个简单的提取请求,并试图映射响应以显示在页面上。

当我console.log(data)时,API结果正确显示,但是一旦添加映射功能,它们就会显示为未定义。我已经尝试过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 :(得分:0)

不确定数据的结构是什么,但是部分问题是您试图在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" />

答案 1 :(得分:0)

我们不太确定您的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>

您可以映射数组并逐项记录每个项目

由于我们只想记录项目,所以我们不需要在这里使用mapforEach就足够了。

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>