Axios with random API - reactjs

I am trying to use random API in my application using axios and I get error that "TypeError: randomData.map is not a function". Maybe someone could tell me what I'm doing wrong?
import './App.css';
import {useEffect, useState} from "react";
import axios from 'axios';
function App() {
const [randomData, setRandomDate] = useState([])
useEffect(() => {
axios.get('https://randomuser.me/api')
.then(res => {
console.log('Getting from: ', res.data)
setRandomDate(res.data)
})
.catch(err => console.log(err))
}, [])
const arr = randomData.map((data, index) => {
return (
<p>{data}</p>
)
})
return (
<div className="App">
<h1>Learning React:</h1>
{arr}
</div>
);
}
export default App;

Your issue is that randomuser api returns an object
{
info: ...,
results: [{}]
}
so when you setRandomData to just res.data, you are assigning an object to your state, and map is not part of an object prototype.
What you need to do is to replace setRandomDate(res.data) with setRandomDate(res.data.results) and now you will be able to map that array.
like
const arr = randomData.map((data, index) => {
return (
<p>{data.email}</p>
)
})

Related

Why doesn't the axios response get saved in useState variable

I've built a random photo displaying feature in react.
the console says that the response is valid and it works,
but the page breaks when I return data.
Where is the issue?
Thanks in advance!
import React from 'react'
import { useEffect, useState } from 'react'
import axios from 'axios'
function RandomPhoto() {
const url = `https://api.unsplash.com/photos/random/?client_id=${process.env.REACT_APP_UNSPLASH_KEY}`
const [data, setData] = useState()
const getPhoto = () => {
axios.get(url)
.then(response => {
setData(response.data)
console.log(response.data) // <------- works
})
.catch(error => {
console.log(error)
})
}
useEffect(() => {
getPhoto()
},[])
console.log("XX" + data) // <---------- doesn't work, and following return() neither
return (
<div>
<img href={data.urls.regular} alt={data.alt_description}/>
<p>Photo by {data.username} {data.name} from {data.location} - found on unsplash</p>
</div>
)
}
export default RandomPhoto
I modified your code a bit, and it's working. I made it as an async function and changed the path of JSON object keys.
Please note the location data sometimes returns as null. So you have to render it conditionally.
import React from 'react';
import { useEffect, useState } from 'react';
import axios from 'axios';
const RandomPhoto = () => {
const url = `https://api.unsplash.com/photos/random/?client_id=${process.env.REACT_APP_UNSPLASH_KEY}`;
const [imageData, setImageData] = useState('');
const getPhoto = async () => {
await axios
.get(url)
.then((response) => {
setImageData(response.data);
})
.catch((error) => {
console.log(error);
});
};
useEffect(() => {
getPhoto();
}, []);
return (
<div>
<p>Hello</p>
<img src={imageData.urls?.regular} />
<p>
Photo by {imageData?.user?.username} {imageData?.user?.name} from{' '}
{imageData?.location?.country} - found on unsplash
</p>
</div>
);
};
export default RandomPhoto;

I have a problem making a request to the StarWars API

I am a person who is learning to use APIs with react and i have a problem because my code does not work. I get the following error in the console: Uncaught TypeError: Cannot read properties of undefined (reading 'map') App.jsx:24
.However I have optional chaining applied.
I show you my code and I hope you can help me
useFetch.js
import axios from "axios"
import { useEffect, useState } from "react"
const useFetch = url => {
const [response, setResponse] = useState()
useEffect( () => {
axios.get(url)
.then(res=>setResponse(res.data))
.catch(err=> console.log(err.message))
}, [])
return response
}
export default useFetch
App.jsx
import axios from 'axios'
import { useEffect, useState } from 'react'
import './App.css'
import FormInput from './components/FormInput'
import Residents from './components/Residents'
function App() {
const [planets, setPlanets] = useState()
const [response, setResponse] = useState()
const number = parseInt(response)
const updatePage = number => {
const URL = `https://swapi.dev/api/planets/${number}/`
axios.get(URL)
.then(res => setPlanets(res.data))
.catch(err => console.log(err.message))
}
useEffect(() => {
const URL = `https://swapi.dev/api/planets/${number}/`
axios.get(URL)
.then(res => updatePage())
.catch(err => console.log(err.message))
}, [])
console.log(number)
return (
<div className="App">
<FormInput
setResponse={setResponse}
/>
<hr />
{
planets?.residents.map(resident => (
<Residents
resident={resident}
key={resident.name}
/>
))
}
</div>
)
}
export default App
Residents.jsx
import React from 'react'
import useFetch from '../hooks/useFetch'
const Residents = ({ resident }) => {
const users = useFetch(resident)
console.log(users)
return (
<article>
</article>
)
}
export default Residents
It's because your residents is not an array. Make it array first or something you are storing in resident is not a object and map() method only works on array not on object. So fix it.
planets?.residents?.map()
use "?" after residents and your residents is not an array. So you need to make it array or whatever you are storing in you residents variable is not an array please cross check you variable/state.

error due to usecontext returning undefined value before bringing the correct array

I've built a code at codesandbox so I could display what is going on.
When I uncomment the <p>{chosenPokemon[0].id}</p> line in the aplication run a error: Cannot read properties of undefined (reading 'id'). Here is the file where the problem is going on:
import { usePokemon } from "../../hooks/usePokemon";
export const MapTest = () => {
const { chosenPokemon } = usePokemon("ditto");
console.log(chosenPokemon);
return (
<>
<h1>Map Test</h1>
{/* <p>{chosenPokemon[0].id}</p> */}
</>
);
};
My conclusion is that my context file is bringing a undefined value before bringing the correct one. Here is my context file:
import { createContext, useContext, useState, useEffect } from "react";
import axios from "axios";
const DittoContext = createContext();
export default function DittoProvider({ children }) {
const [ditto, setDitto] = useState();
const api = axios.create({
baseURL: "https://pokeapi.co/api/v2/pokemon"
});
useEffect(() => {
api
.get("/ditto")
.then((response) => setDitto(response.data))
.catch((err) => console.log(err));
}, []);
return (
<DittoContext.Provider value={{ ditto, setDitto }}>
{children}
</DittoContext.Provider>
);
}
export const useDitto = () => {
const context = useContext(DittoContext);
const { ditto, setDitto } = context;
return { ditto, setDitto };
};
How can I fix this error that has been going on?

map array of objects from an api react

I have been trying to get the images from this API to append to the page by mapping through them, but I keep getting one of two error messages saying 'undefined.map is not a function' or 'getBirds.map is not a function.'I've tried leaving the array of objects as it is and setting state to an object and an array(at separate times) but that didn't work. I've also tried using Object.key, Object.values, and Object.entries(each at separate times) to turn the array of objects into an array and then map through my variable and through getBirds(again separately) but those attempts also failed. I have attached three of my attempts below. Can someone help me understand where I've gone wrong?
// Attempt 1
import {useState, useEffect} from 'react'
import axios from 'axios'
function Birds(props) {
const [getBirds, setGetBirds] = useState({})
const {image} = props
useEffect(() => {
async function fetchBirds() {
const URL = `https://audubon-society-api.herokuapp.com/birds`
try {
const res = await axios.get(URL)
console.log(res.data)
setGetBirds(res.data)
} catch (error) {
console.log(error)
}
}
fetchBirds()
}, [])
if (!getBirds) return <h3>Loading...</h3>
return (
<div>
<img src={getBirds.map(image)} alt={getBirds.map(image)}></img>
</div>
)
}
export default Birds
// Attempt 2
import {useState, useEffect} from 'react'
import axios from 'axios'
function Birds(props) {
const [getBirds, setGetBirds] = useState([])
const {image} = props
useEffect(() => {
async function fetchBirds() {
const URL = `https://audubon-society-api.herokuapp.com/birds`
try {
const res = await axios.get(URL)
console.log(res.data)
setGetBirds(res.data)
} catch (error) {
console.log(error)
}
}
fetchBirds()
}, [])
if (!getBirds) return <h3>Loading...</h3>
return (
<div>
<img src={getBirds.map(image)} alt={getBirds.map(image)}></img>
</div>
)
}
export default Birds
// Attempt 3
import {useState, useEffect} from 'react'
import axios from 'axios'
function Birds(props) {
const [getBirds, setGetBirds] = useState({})
const {image} = props
useEffect(() => {
async function fetchBirds() {
const URL = `https://audubon-society-api.herokuapp.com/birds`
try {
const res = await axios.get(URL)
console.log(res.data)
setGetBirds(res.data)
} catch (error) {
console.log(error)
}
}
fetchBirds()
}, [])
const birds = Object.entries(getBirds)
birds.forEach(([key, value]) => {
console.log(key, value)
})
if (!getBirds) return <h3>Loading...</h3>
return (
<div>
<img src={birds.map(image)} alt={birds.map(image)}></img>
</div>
)
}
export default Birds
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
You would need to initialize your state with an array, so the map function won't get errors, and correct the way you map it:
Initialize state with an array:
const [getBirds, setGetBirds] = useState([]);
Map it:
return (
<div>
{getBirds.map((bird) => (
<img src={bird.image} alt={bird.image}></img>
))}
</div>
);
Also, check your array with length, because [] or {} both equal to true.
if (!getBirds.length) return <h3>Loading...</h3>;
console.log(!![]);
console.log(!!{});
console.log(!![].length)
The completed solution:
import { useState, useEffect } from "react";
import axios from "axios";
function Birds(props) {
const [getBirds, setGetBirds] = useState([]);
useEffect(() => {
async function fetchBirds() {
const URL = 'https://audubon-society-api.herokuapp.com/birds';
try {
const res = await axios.get(URL);
console.log(res.data);
setGetBirds(res.data);
} catch (error) {
console.log(error);
}
}
fetchBirds();
}, []);
if (!getBirds.length) return <h3>Loading...</h3>;
return (
<div>
{getBirds.map((bird) => (
<img src={bird.image} alt={bird.image}></img>
))}
</div>
);
}
export default Birds;
Working Example:
Your init state of birds and setBirds should be an array [] not an object {}, also you don't need:
const birds = Object.entries(getBirds). fetch return array of birds already.
<img src={birds.map(image)} alt={birds.map(image)}></img> is wrong, the array loop map should render an image for each bird.
Below code will run for your need:
import React, {useState, useEffect} from "react";
import axios from 'axios';
function Birds(props) {
//- const [getBirds, setGetBirds] = useState([])
//- const {image} = props
// +
const [birds, setGetBirds] = useState([])
useEffect(() => {
async function fetchBirds() {
const URL = `https://audubon-society-api.herokuapp.com/birds`
try {
const res = await axios.get(URL)
console.log(res.data)
setGetBirds(res.data)
} catch (error) {
console.log(error)
}
}
fetchBirds()
}, [])
// - const birds = Object.entries(getBirds)
// - birds.forEach(([key, value]) => {
// - console.log(key, value)
// - })
// - if (!getBirds) return <h3>Loading...</h3>
if (!birds) return <h3>Loading...</h3>
return (
<div>
{/* <img src={birds.map(image)} alt={birds.map(image)}></img> */}
{birds.map((item, index) =>
<img src={item.image} alt={index}></img>
)}
</div>
)
}
export default Birds

Store api response to an array using react useState

I am new to react hooks. I am trying to cast API response into an array using react useState hook. It's giving me empty with the below approach
const [post, setPostArray] = useState([]);
useEffect(() => {
const postparams = { userList: result };
axios
.get(environment._urlPosts, { headers, params: postparams })
.then(posts => {
// storing response data in array
setPostArray(posts.data.post);
console.log(post);
})
.catch(err => {});
}, []);
Then I used the below approach and I was able to see data is printing in the console log
axios.get(environment._urlPosts, { headers, params: postparams }).then(posts => {
// storing response data in array
for (let obj of posts.data.post) {
post.push(obj)
}
setPostArray(post)
console.log(post)
But when I try to iterate this post array in my JSX, it's giving me empty array.
</div>
{/* array length */}
{post.length}
{post.map(post =>
<div className="card">
<Post username={post.username} fullname={post.fullname} postedTime={post.postedTime} postContent='Hi' tweeterLike={post.tweeterLike} />
</div>
)}
Can you please help me to resolve this?
Here is a minimal Example of what you are trying to achieve.
This is the working code:
import React, {useEffect, useState} from "react";
import "./styles.css";
export default function App() {
const [post, setPostArray] = useState([])
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
console.log(json);
setPostArray([json]);
})
// setPostArray([{name: 'a'}, {name: 'b'},{name: 'c'}])
},[])
console.log(post)
return (
<div className="App">
{
post.map(item => <div>{item.title} </div>)
}
</div>
);
}
Here is the link to the example in codeSandBox: https://codesandbox.io/s/jovial-snow-773kp

Resources