简体   繁体   中英

data scope in React using Fetch

I am trying to understand how can I use fetch to get data from an API and use it to create React components. I am a bit confuse if this is the correct method to retrieve, store and use the data, or if there is another way that I might not be aware (I read something in the docs about states and mounts but I could not get my head around it.

JS

//Data
const url = 'https://api.tfl.gov.uk/BikePoint'; // API

fetch(url)
.then((resp) => resp.json()) // Transform the data into json
.then(function(data) {
  // How can I make data accessible outside this function?
 })

.catch(function(error) {
  console.log(JSON.stringify(error));
});

//React
const List = ({items, each}) =>

  <div className = "panel panel-default">
  <div className = "panel-heading"><h2>Bike points</h2></div>
    <div className = "panel-body">   

      <ul className = "list-group">{items.map((item, key) =>
        <ListItem key = {key} item = {each(item)} number={item.commonName}/>)}</ul>

    </div>
  </div>

const ListItem = ({item, arrival, number}) =>
  <li className = "list-group-item">{number}</li>

//How can access the data here?
ReactDOM.render(<List items={data} each={ListItem} />, document.querySelector('#main'))

CodePen

I would appreciate if you could point me out to any resource that can help me understand this concept. Thank you in advance.

In your example code, you're not returning the 'resp.json()', resp.json() will return a promise, you need to return this and if it resolves successfully, then 'data' in your next .then() will be populated with the object from the API response. You may then want to set the the response data in your component state to do something.

I've created a simple react app with 'create-react-app' to demonstrate this:

import React, { Component } from 'react'; //import 'React' default export, and { Component } non-default export from react
import fetch from 'isomorphic-fetch'; // isomorphic-fetch is used for both server side and client side 'fetch' (see https://github.com/matthew-andrews/isomorphic-fetch)
// App.css was a hangover from the create-react-app, it's not really needed for this basic example
const url = 'https://api.tfl.gov.uk/BikePoint'; // API




class App extends Component { // This is the same as 'extends 'React.Component'

    constructor(props) {
        super(props);
        this.state = {
            fetchedData: null // stores the result of the fetch response body converted to a javascript object
        };
    }

  fetchIt = () => {
      console.log('fetching it');
      fetch(url, { mode: 'cors' }) // Make sure fetch is cross-origin, it's not by default (see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) since the target URL of the API is a different 'origin' to our react app
          .then((resp) => {
            console.log(resp);
          return resp.json(); })
          .then((data) => { // data input parameter is the result of the resolved resp.json() Promise (see https://developer.mozilla.org/en-US/docs/Web/API/Body/json)
              console.log(data);
              this.setState({ fetchedData: data }); // setState sets the component state with the data from the API response
          })
          .catch(function(error) {
              console.log(JSON.stringify(error));
          });
  }



  render() {
      if(!this.state.fetchedData){ // only do the fetch if there is no fetchedData already (BTW this will run many times if the API is unavailable, or 'fetchIt() encounters an error)
          this.fetchIt();
      }

    return (
      <div>
          {
              this.state.fetchedData ? `fetched ${this.state.fetchedData.length} entries`  : 'no data' // This is a 'ternary' expression, a simple 'if->else'
              /* equivalent to:

                if(this.state.fetchedData) {
                    return `fetched ${this.state.fetchedData.length} entries`; // this is 'javascript string interpolation'
                } else {
                    return 'no data';
                }
              *
              * */
          }
      </div>
    );
  }
}

export default App; // Export our component to be used by other react higher order components (parents), in this case, it's imported in 'index.js', data is only fetched when the component renders.

Working github repo here: https://github.com/finbarrobrien/fetchy/blob/master/src/App.js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM