Whenever I get data on my page, after a few seconds, my whole react app disappears as in the root div in the html is left completely empty like this <div id="root"></div>
as if there is nothing. This is happening on all my other projects too even when I create a new one, this disappearing of the react keeps happening sometimes even without adding any logic, it refuses to render plain html. The errors I get for now on this current project on the console is this
characters.map is not a function
I know not what could be causing this but my code looks like this for now starting with the App.js file. I am extracting data from an api.
import {BrowserRouter, Route, Routes} from "react-router-dom" import Home from "./components/Home"; function App() { return ( <div className="App"> <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> </Routes> </BrowserRouter> </div> ); } export default App;
And then followed by the CharactersListing page which is supposed to render all the characters of the show
import React, {useEffect, useState} from 'react' import CharacterCard from './CharacterCard' export default function BadListings() { const [characters, setCharacters] = useState([]) useEffect(() => { const getData = async () => { await fetch("https://www.breakingbadapi.com/api/characters") .then(response => { setCharacters(response.json()); console.log(characters); }) .catch(err => console.log("There must have been an error somewhere in your code", err.message)); } getData(); }); return ( <div className='container'> {characters.map(character => ( <div> <CharacterCard name={character.name} status={character.status} image={character.img} /> </div> ))} </div> ) }
And finally, the CharacterCard.js
import React from 'react' import "../styles/styles.css" export default function CharacterCard({name, status, image}) { return ( <div className='card'> <h1>{name}</h1> <h2>{status}</h2> <img src={image} alt="umfanekiso" className='imgur' /> </div> ) }
I do not know what could be causing this. I have never had this issue it just started today. What could be causing it
Advertisement
Answer
Issues
The issue is that you are not setting the characters
state to what you think it is. response.json()
returns a Promise object and doesn’t have a map
property that is a function to be called.
The useEffect
hook is also missing a dependency, so anything that triggers this BadListings
component to rerender will also retrigger this useEffect
hook, which updates state and triggers another rerender. The code is likely render looping.
Solution
- The code should wait for the
response.json()
Promise to resolve and pass that result value into thecharacters
state updater function. Note that I’ve also rewritten the logic to useasync/await
withtry/catch
as it is generally considered anti-pattern to mixasync/await
with Promise chains. - Add a dependency array to the
useEffect
hook. Since I don’t see any dependencies use an empty array so the effect runs only once when the component mounts.
Promise chain Example:
useEffect(() => { fetch("https://www.breakingbadapi.com/api/characters") .then(response => response.json()) // <-- wait for Promise to resolve .then(characters => setCharacters(characters) .catch(err => { console.log("There must have been an error somewhere in your code", err.message) }); }, []); // <-- add empty dependency array
async/await
Example:
useEffect(() => { const getData = async () => { try { const response = await fetch("https://www.breakingbadapi.com/api/characters"); const characters = await response.json(); // <-- wait for Promise to resolve setCharacters(characters); } catch(err) { console.log("There must have been an error somewhere in your code", err?.message); }; } getData(); }, []); // <-- add empty dependency array
Don’t forget to add a React key to the mapped characters:
{characters.map((character) => ( <div key={character.char_id}> // <-- Add React key to outer element <CharacterCard name={character.name} status={character.status} image={character.img} /> </div> ))}