LogoLogo
  • FAC Curriculum
  • archive
    • Node & npm introduction
    • developer
      • Programming Paradigms
    • handbook
      • Asking for help
      • Coaching groups
      • Code review
      • Course rules
      • Debugging
      • Employment schedule and material delivered in FAC20
      • GitHub Workflow
      • Glossary or terms
      • Presentation Guidance
      • Equality, Diversity and Inclusion
      • Installation guide
      • Learning circles
      • Mentoring guidance
      • What to expect from your mentors
      • One-day projects
      • Pair programming
      • Portfolio
      • Questions for problem solving
      • Progress Logs
      • Final project report
      • Managing software projects
      • Project Presentations
      • Project roles
      • Projects
      • Retrospectives
      • Role Circles
      • Safeguarding policy
      • Technical Spikes
      • System requirements
      • Tech for Better
      • User Manuals
      • Wellbeing Support
      • project-docs
        • What makes a mentor?
        • Product Handover
        • Sprint Planning
        • Tech for Better Presentations
        • User Research & Usability Testing
    • foundation
      • full-stack
        • Learning Outcomes
        • project
      • testing
        • project
        • spikes
  • docs
    • Contributing to the curriculum
    • Curriculum intent
    • Curriculum process
  • src
    • About our curriculum
    • course
      • Code of Conduct
      • Docker
      • .NET and Umbraco
      • Getting started
      • Founders and Coders coursebook
      • KSB's
      • Mini projects
      • Revision checklist
      • Svelte
      • TypeScript
      • handbook
        • Software Developer Handbook
        • Software Foundation Handbook
      • precourse
        • Before you start the course
        • Installation List
      • syllabus
        • developer
          • app
            • learning-outcomes
            • project
            • schedule
            • spikes
          • introduction
            • learning-outcomes
            • project
            • resources
            • schedule
          • week00-pre-course
            • We'd like you to spend some time before starting the course working on useful fundamentals.
            • spikes
          • week01-project01-basics
            • Employability introduction
            • Homework
            • learning-outcomes
            • Week of September 9th
            • project
            • resources
            • schedule
            • spikes
          • week02-project02-chatbot
            • employability
            • Homework
            • learning-outcomes
            • Week of September 16th
            • project
            • resources
            • schedule
            • spikes
          • week03-project03-server
            • Learning Outcomes
            • Week of September 23th
            • The Amazin' Quizzer API Backend
            • resources
            • schedule
          • week04-project03-frontend
            • learning-outcomes
            • Week of September 30th
            • UI for Quizzer App
            • resources
            • schedule
          • week05-project03-test-deploy
            • Testing and deployment
            • Week of October 7th
            • project
            • resources
            • schedule
          • week06-project04-databases
            • learning-outcomes
            • Week of October 14th
            • project
            • Databases
            • schedule
          • week07-project04-authentication
            • Learning Outcomes
            • Week of October 21st
            • project
            • resources
            • schedule
          • week08-project04-test-deploy
            • Learning Outcomes
            • Week of October 28th
            • project
            • resources
            • schedule
          • week09-reading-week
            • Learning Outcomes
            • overview
            • Project
            • Resources
            • schedule
          • week10-project05-DOTNET-intro
            • Learning Outcomes
            • overview
            • project
            • Resources
            • schedule
          • week11-project05-DOTNET-testing
            • Testing and deployment
            • Week of November 18th
            • project
            • Resources
            • schedule
          • week12-project05-DOTNET-deploy
            • Learning Outcomes
            • Week of November 25th
            • project
            • Resources
            • schedule
            • Spikes
          • week13-TFB-design
            • Learning Outcomes
            • overview
            • Project
            • Resources
            • schedule
            • Design Week Spikes
          • week14-TFB-build
            • Learning Outcomes
            • overview
            • Project
            • DevOps Resources
            • schedule
            • Spikes
          • week15-TFB-build
            • Learning Outcomes
            • overview
            • Project
            • Resources
            • schedule
            • Spikes
          • projects
            • in-house-design
              • Learning Outcomes
              • Project
              • Resources
              • schedule
              • Design Week Spikes
        • foundation
          • Obsolete-full-stack
            • project
          • post-course
            • Homework
            • schedule
        • portfolio
          • fruit-shop
            • learning-outcomes
            • project
            • resources
          • game
            • learning-outcomes
            • project
            • resources
          • hobby-page
            • learning-outcomes
            • project
            • resources
          • movie-data
            • learning-outcomes
            • project
            • resources
          • project-gallery
            • learning-outcomes
            • project
            • resources
          • website
            • learning-outcomes
            • project
            • JavaScript
        • tfb
          • week 1
            • Introduction (45 minutes)
            • Further reading
          • week 10
            • content
            • resources
          • week 11
            • What will we be doing this week?
            • resources
          • week 12
            • What will we be doing this week?
            • Further reading
          • week 2
            • Discover (90 minutes)
            • resources
          • week 3
            • content
            • resources
          • week 4
            • Mapping the user journey (90 minutes)
            • resources
          • week 5
            • Figma Workshop 1 (90 minutes)
            • Further reading
          • week 6
            • Figma Workshop 2 (90 minutes)
            • resources
          • week 7
            • Product pitches & Selection (90 minutes)
            • resources
          • week 8
            • content
            • resources
          • week 9
            • content
            • resources
    • learn
      • DOTNET
        • Introduction to .NET
      • auth
        • Authenticating web apps
      • database
        • Persisting data with SQLite and Node
      • dotnet-two
        • Dependency injections and interfaces in .NET
      • form-validation
        • Form validation
      • react
        • Building client-side apps with React
      • server
        • HTTP servers with Node & Express
      • typescript
        • TypeScript
    • mentoring
      • design-week
        • Analysis Workshop
        • Code planning
        • Definition Workshop
        • Discovery Workshop
        • Figma introduction
        • Usability testing
        • User Research
    • resources
      • http
        • introduction
    • workshops
      • cookie-auth
        • index
      • creating-promises
        • index
      • css-layout
        • index
      • cypress-testing
        • index
      • database-testing
        • index
      • dev-tooling
        • Developer tooling
      • dom-challenge
        • index
      • dom-rendering
        • index
      • es-modules
        • index
      • express-middleware
        • Express middleware
      • first-class-functions
        • index
      • form-validation
        • index
      • functions-callbacks-async
        • Functions, callbacks, & async JavaScript
      • git-intro
        • Introduction to Git
      • git-terminal
        • Using Git in the terminal
      • git-workflow
        • Git workflow
      • github-projects
        • GitHub Projects Workflow Workshop
      • heroku-sql-challenge
        • index
      • html-forms
        • index
      • learn-a11y
        • index
        • starter-files
          • solution
            • Accessibility solution explanation
      • learn-fetch
        • index
      • learn-integration-testing
        • index
      • learn-testing
        • Learn testing in JavaScript
      • learn-unit-testing
        • index
      • node-error-handling
        • Node error-handling
      • node-express-server
        • Node and Express HTTP server
      • node-npm-intro
        • Node & npm introduction
      • node-postgres
        • Learn Postgres with Node
      • node-scripting-challenge
        • index
      • password-security
        • index
      • promise-practice
        • index
      • react-components
        • React components
      • react-fetch
        • index
      • react-forms
        • React forms
      • react-refactor-classes
        • index
      • react-state-effects
        • React state & effects
      • real-world-fetch
        • index
      • scope-challenge
        • Scope debugging challenge
      • semantic-html
        • index
      • server-side-forms
        • Server-side forms
      • session-auth
        • Session authentication
      • sql-intro
        • index
      • tdd-array-methods
        • index
Powered by GitBook
On this page
  • Setup
  • Managing effects
  • Fetching data
  • Avoiding infinite loops
  • Challenge 1: user profile
  • Re-running effects
  • Challenge 2: re-usable profile
  • Passing state down
  • Challenge 3: searching for users
  • Stretch goal: fetching repos
Export as PDF
  1. src
  2. workshops
  3. react-fetch

index

Learn how to fetch data from APIs in your React components

React doesn't have a built-in pattern designed for fetching data. This can make it a little confusing at first, so let's look at how we can combine useState and useEffect to create a GitHub profile page.

Setup

  1. Download starter files and cd in

  2. npm install

  3. npm run dev

The index.html file loads workshop/index.jsx. This imports workshop/App.jsx and renders the component using React.

Managing effects

React components are designed to keep the DOM in-sync with your app's data. For example this component will re-render every time the name prop changes, ensuring the message is always correct:

function Greeting({ name }) {
  return <div>Hello {name}!</div>;
}

However some parts of your app cannot be represented with JSX, as they are not part of the DOM. React calls these "effects"—they are extra things your component does (other than the primary task of rendering DOM elements).

In order to ensure React can keep track of these effects and re-run them when our app's data changes we pass them in to the React.useEffect function.

Fetching data

Fetching data is one of these "effects". We run our fetch request inside useEffect so React can control when it runs (or re-runs).

function Pokemon() {
  React.useEffect(() => {
    fetch("https://pokeapi.co/api/v2/pokemon/pikachu")
      .then((res) => res.json())
      .then((data) => console.log(data));
  });

  return <div>Hello</div>;
}

We have a problem here: our API request could take 10 seconds to finish. However React components are synchronous—they must render something straight away. We cannot wait for the response to be done before returning a value.

Instead we need to update our component with the new data once the response finishes. We can make a component update by setting state. Remember that a component will re-run whenever its state values change.

function Pokemon() {
  const [pokeData, setPokeData] = React.useState(null);

  React.useEffect(() => {
    fetch("https://pokeapi.co/api/v2/pokemon/pikachu")
      .then((res) => res.json())
      .then((data) => setPokeData(data));
  });

  return <div>Hello</div>;
}

We can't use this data immediately, since the API request is asynchronous. Our component will render at least once with the initial state, which here is null.

The easiest way to make sure the data has loaded before we use it is to check whether the state variable is there:

function Pokemon() {
  const [pokeData, setPokeData] = React.useState(null);

  React.useEffect(() => {
    fetch("https://pokeapi.co/api/v2/pokemon/pikachu")
      .then((res) => res.json())
      .then((data) => setPokeData(data));
  });

  if (!pokeData) {
    return <div>Loading...</div>;
  } else {
    return <div>{pokeData.name}</div>;
  }
}

Here's the flow of our component's updates:

  1. The component is rendered (i.e. <Pokemon /> somewhere)

  2. React calls the Pokemon function

  3. React creates the pokeData state (because we called useState)

  4. React queues an effect to run (because we called useEffect)

  5. pokeData is null so JS runs the first if branch

  6. The component returns <div>Loading...</div>

  7. The queued effect runs, which sends a fetch request

Some time passes...

  1. The fetch request resolves with the response data

  2. Our .then sets the pokeData state as the response object

  3. React sees the state update and re-runs the component function

  4. This time the pokeData state variable is the response object (not null)

  5. So JS runs the second if branch and returns <div>pikachu</div>

Avoiding infinite loops

There is one final problem to solve: our component currently always queues a new effect. This means that after our component's state updates (and re-renders the component) it'll send a new fetch request. When this request resolves it'll update the state, re-rendering the component. This will trigger another fetch, and so on.

To avoid this infinite loop we need to constrain when the effect runs, by providing the dependencies array as the second argument. This tells React that the effect only needs to re-run if the things inside the array have changed.

In this case our effect has no dependencies, since it doesn't use any values from outside the effect. So we can specify an empty array:

React.useEffect(() => {
  // ...
}, []);

This tells React "you won't need to re-run this effect, since it doesn't depend on any values that might change and get out of sync".

Challenge 1: user profile

You're going to build a Profile component that fetches a user from the GitHub API and renders their name, avatar image and any other details you like.

  1. Create a new component in workshop/Profile.jsx

  2. It should fetch your profile from "https://api.github.com/users/{username}"

  3. It should render a loading message until the request is done

  4. It should render at least your name & avatar image once the request completes

Re-running effects

Our Profile component would be more useful and reusable if it could fetch any user's GitHub information. Components can be customised by passing in props (just like function arguments). We want to be able to do this:

<Profile name="oliverjam" />

and have the component fetch that user's profile.

Challenge 2: re-usable profile

  1. Amend Profile to take a name prop

  2. Use this prop to fetch the right data from GitHub

  3. Pass a name to <Profile /> inside App

Passing state down

Our Profile component can now fetch any user, but we still have to hard-code the prop when we render it in App. Ideally we'd let users type the name into a search input, then update the prop we pass down when they submit.

We can achieve this with a state value in App that keeps track of the current value of name. When the form is submitted you can update that state value, which will cause the App component to re-render. This will then cause Profile to re-render with the new value of name passed as a prop.

Challenge 3: searching for users

  1. Add a form with a search input to App

  2. Add a name state value to App

  3. When the form is submitted update the state value

  4. Pass the state value to Profile so it knows which name to fetch

Stretch goal: fetching repos

The user response object from GitHub contains a repos_url property. This is a URL from which you can fetch an array of the user's repositories. To display the user's repos underneath their other info we'll have to make another fetch after the first one resolves.

The simplest way to achieve this is by creating a new component that takes the repos_url as a prop, fetches the data, then renders the list of repos.

  1. Create a new component in ReposList.jsx

  2. It should receive a URL as a prop and fetch the repos from it

  3. When it receives a response it should render a list of repos

  4. Amend Profile to render ReposList and pass in the right URL prop

Previousreact-fetchNextreact-forms

Last updated 4 years ago