I am needing to fetch data from the MovieDB API and I have my code setup to where I just want to return some data after I hit the search button. But when I hit the search button I get back NetworkError when attempting to fetch resource
My code so far consists of this
import React, {useEffect, useState} from 'react';
import './App.css';
const App = () => {
const API_KEY = '664e565dee7eaa6ef924c41133a22b63';
const [movies, setMovies] = useState([]);
const [query, setQuery] = useState("");
useEffect(() => {
async function getMovies(){
const response = await fetch(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}`)
const data = await response.json()
console.log(data.results)
setMovies(data.results)
}
if(query !== "") getMovies();
}, [query])
return (
<div>
<form>
<button onClick={() => setQuery("Avengers")}type="submit">Search</button>
<p>{JSON.stringify(movies)}</p>
</form>
</div>
);
}
export default App;
If use (and query ='Avengers'):
${query}`
in API URL, you get this (Every record is corelated with Avengers movie)
Try this - It's not include more advanced functions, which you need.
But it's good fundamental for bulding next features:
import React, { useEffect, useState } from 'react';
const App2 = () => {
const API_KEY = '664e565dee7eaa6ef924c41133a22b63';
const [movies, setMovies] = useState([]);
const [query, setQuery] = useState('Avengers');
useEffect(() => {
async function getMovies(query) {
await fetch(`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=$query`)
.then(data => data.json())
.then(data => {
console.log(data.results)
const result = data.results.map(obj => ({ popularity: obj.popularity, id: obj.id }));
console.log(result)
setMovies(result)
console.log(movies)
})
}
getMovies()
}, [query])
return (
<div>
{movies.map((movie, key) => (
<div key={key}>
<h1> {movie.popularity}</h1>
<h1>{movie.id}</h1>
</div>
))}
</div>
);
}
export default App2;
Here is your schema from API (only 1 object in array) (I used only id & popularity) - it's possible to use what you wish:
Related
I'm facing difficulty displaying data in React - Here is my code:
import Axios from 'axios';
import { useNavigate } from 'react-router';
export default function ProductCatalog() {
let navigate = useNavigate();
function addProduct() {
navigate('/adding')
}
const [products, setProducts] = useState([{}])
useEffect(() => {
const axiosProd = async () => {
const response = await Axios('http://localhost:3001/getProducts');
setProducts(response.data)
};
axiosProd();
}, []);
const useProducts = products.map((product)=>{
return <div>
<h1>{product.name}</h1>
</div>
})
return(
<>
<button className = "button" onClick={addProduct}>Add New Product</button>
<br></br>
{useProducts}
</>
)
}
I know data is coming in as JSON Objects as when i follow the link of http://localhost:3001/getProducts, I see my data. What am i doing wrong?
You should make a function then outside of the function call the use effect.
To do a get request using axios use axios.get(api)
For example:
// Get All Shoes
const getShoes = () => {
axios.get('/shoes')
.then(res => setShoes(res.data))
.catch(err => console.log(err));
}
Then
useEffect(() => {
getShoes();
}, [])
this is my react code here I fetch the data from the backend using mongo. my data is appearing in the console but not appearing on the web page it's showing `users.map is not a function. but if I try the jsonplaeholder API then its work properly.
import React, { useEffect, useState } from "react";
const Get = () => {
const [users,setUsers] = useState([]);
const getAllUser = async () => {
const response = await fetch("/get");
setUsers(await response.json());
console.log(users);
};
useEffect(() => {
getAllUser();
},[]);
return (
<>
{ users.map((ce) =>
<div key={ce.id}>
<h2>{ce.name}</h2>
<p>{ce.email}</p>
</div>)}
</>
)
}
export default Get;
this is the db data
{"status":"success","results":2,"data":{"users":[{"_id":"6134fcc6eddae0ec522fecd7","name":"ram ","email":"ram#gmail.com","number":9455294552,"__v":0},{"_id":"61364d918a8ab07512094443","name":"rawal","email":"rawal#gmail.com","number":9309304400,"__v":0}]}}
You need to properly set your state with res.data.users as follows.
import React, { useEffect, useState } from "react";
const Get = () => {
const [users, setUsers] = useState([]);
const getAllUser = async () => {
const response = await fetch("/get");
response.json().then((res) => setUsers(res.data.users));
console.log(users);
};
useEffect(() => {
getAllUser();
}, []);
return (
<>
{users.map((ce) => (
<div key={ce.id}>
<h2>{ce.name}</h2>
<p>{ce.email}</p>
</div>
))}
</>
);
};
export default Get;
I am working on an API app that will return a list of jobs when user enter the job description or location. Initially, the page will return all jobs and display them to the screen at the first render (default useEffect). Now I want when the user clicks on the button, page will render a list of job based on user's inputs. How do I do that on my onSubmit function in order to update the value of useEffect hooks?
import React, { useState, useEffect} from 'react';
import SearchForm from './componenets/Form.js';
import JobLists from './componenets/JobLists'
import axios from 'axios'
function App() {
const [posts, setPosts] = useState([]) //posts store a list of jobs
const [description, setDescription] = useState('') //description of the job (user's input)
const [location, setLocation] = useState('') //location of the job (user's input)
//description input handle
const handleDescriptionChange = (e) => {
setDescription(e.target.value);
}
//location input handle
const handleLocationChange = (e) => {
setLocation(e.target.value);
}
//submit button handle
const onSubmit = e => {
e.preventDefault();
//once the user enter input and clicks on button, update the the useEffect hooks
}
//get data from github job API (fetching by description and location)
const url = `https://cors-anywhere.herokuapp.com/https://jobs.github.com/positions.json?description=${description}&location=${location}`
useEffect(() => {
axios.get(url)
.then(res =>{
console.log(res)
setPosts(res.data)
})
.catch(err =>{
console.log(err)
})
}, [])
return (
<div>
<SearchForm
description={description}
handleDescriptionChange={handleDescriptionChange}
location={location}
handleLocationChange={handleLocationChange}
onSubmit={onSubmit} />
{
posts.map((job) => <JobLists job={job} key={job.id} />) //map through each job
}
</div>
)
}
export default App;
https://codesandbox.io/s/react-form-example-gm9o6
import React, { useState, useEffect } from 'react'
import SearchForm from './componenets/Form.js'
import JobLists from './componenets/JobLists'
import axios from 'axios'
const App = () => {
const [posts, setPosts] = useState([]) //posts store a list of jobs
const [description, setDescription] = useState('') //description of the job (user's input)
const [location, setLocation] = useState('') //location of the job (user's input)
const url = `https://cors-anywhere.herokuapp.com/https://jobs.github.com/positions.json?description=${description}&location=${location}`
const getPosts = async () => {
await axios
.get(url)
.then((res) => {
console.log(res)
setPosts(res.data)
})
.catch((err) => {
console.log(err)
})
}
//get data from github job API (fetching by description and location)
useEffect(() => {
getPosts()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
//description input handle
const handleDescriptionChange = (e) => {
setDescription(e.target.value)
}
//location input handle
const handleLocationChange = (e) => {
setLocation(e.target.value)
}
//submit button handle
const onSubmit = (e) => {
e.preventDefault()
//once the user enter input and clicks on button, update the the useEffect hooks
getPosts()
}
return (
<div>
<SearchForm
description={description}
handleDescriptionChange={handleDescriptionChange}
location={location}
handleLocationChange={handleLocationChange}
onSubmit={onSubmit}
/>
{
!!posts?.length &&
posts.map((job) => <JobLists key={job.id} job={job} />) //map through each job
}
</div>
)
}
export default App
Here is my entire component. In the console the correct data is showing up at "data" but when I try to run map on it it says "map is not a function." The 16 items in the console are the correct beaches.
import React, {useState, useEffect} from 'react';
import axios from 'axios';
export default function Beaches() {
const [data, setData] = useState({beaches: []})
// const [hasError, setErrors] = useState(false)
useEffect(() => {
const fetchBeaches = async () => {
const result = await axios('http://localhost:3000/beaches');
setData(result.data);}
fetchBeaches();
}, [])
console.log(data)
return (
<ul>
{data.beaches.map(beach => (
<button>{beach.name}</button>
))}
</ul>
)
}
Because you're not setting the beaches data in state correctly.
Replace useEffect code with this:
useEffect(() => {
const fetchBeaches = async () => {
const result = await axios('http://localhost:3000/beaches');
setData({beaches: result.data});
}
fetchBeaches();
}, [])
furthermore, you can improve the state structure of beaches data:
import React, { useState, useEffect } from "react";
import axios from "axios";
export default function Beaches() {
const [beaches, setBeaches] = useState([]);
// const [hasError, setErrors] = useState(false)
useEffect(() => {
const fetchBeaches = async () => {
const result = await axios("http://localhost:3000/beaches");
setBeaches(result.data);
};
fetchBeaches();
}, []);
return (
<ul>
{beaches.map((beach) => (
<button>{beach.name}</button>
))}
</ul>
);
}
I'm trying to take out the fetchImages function from the following component and put it inside a new component:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import UnsplashImage from './UnsplashImage';
const Collage = () => {
const [images, setImages] = useState([]);
const [loaded, setIsLoaded] = useState(false);
const fetchImages = (count = 10) => {
const apiRoot = 'https://api.unsplash.com';
const accessKey =
'<API KEY>';
axios
.get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
.then(res => {
console.log(res);
setImages([...images, ...res.data]);
setIsLoaded(true);
});
};
useEffect(() => {
fetchImages();
}, []);
return (
<div className="image-grid">
{loaded
? images.map(image => (
<UnsplashImage
url={image.urls.regular}
key={image.id}
alt={image.description}
/>
))
: ''}
</div>
);
};
export default Collage;
For this, I created a new component called api.js, removed the entire fetchImage function from the above component and put it in to api.js like this:
api.js
const fetchImages = (count = 10) => {
const apiRoot = 'https://api.unsplash.com';
const accessKey =
'<API KEY>';
axios
.get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
.then(res => {
console.log(res);
setImages([...images, ...res.data]);
setIsLoaded(true);
});
};
export default fetchImages;
Next I took setIsLoaded(true); from api.js and paste it inside Collage component like this:
useEffect(() => {
fetchImages();
setIsLoaded(true);
}, []);
Now I can import fetchImages in to Collage component.
However, I don't know what should I do with this line inside the fetchImages function? This needs to go to Collage component, but res.data is not defined inside Collage component.
setImages([...images, ...res.data]);
How should I handle it?
There is many way to do that, but in your case.
You should use
const fetchImages = (afterComplete, count = 10) => {
const apiRoot = 'https://api.unsplash.com';
const accessKey = '<API KEY>';
axios
.get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
.then(res => {
console.log(res);
afterComplete(res.data);
});
};
export default fetchImages;
And in your Collage component:
const afterComplete = (resData) =>{
setImages([...images, ...resData]);
setIsLoaded(true);
}
useEffect(() => {
fetchImages(afterComplete);
}, []);
What you can do is create a custom hook ( sort of like a HOC)... Since I don't have an unsplash API key I'll give you an example with a different API but the idea is the same:
Here is your custom hook:
import { useState, useEffect } from 'react';
export const useFetch = url => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const fetchUser = async () => {
const response = await fetch(url);
const data = await response.json();
const [user] = data.results;
setData(user);
setLoading(false);
};
useEffect(() => {
fetchUser();
}, []);
return { data, loading };
};
Here is how you can use it in your component:
import { useFetch } from './api';
const App = () => {
const { data, loading } = useFetch('https://api.randomuser.me/');
return (
<div className="App">
{loading ? (
<div>Loading...</div>
) : (
<>
<div className="name">
{data.name.first} {data.name.last}
</div>
<img className="cropper" src={data.picture.large} alt="avatar" />
</>
)}
</div>
);
};
Here is a live demo: https://codesandbox.io/s/3ymnlq59xm