I am a newbie react learner and here trying to make an api call to display list of weather details(for test case I am trying to get "app_max_temp") but I am getting error as "cannot read property of map undefined at SearchCity(SearchCity.js:29)" .I have tried that url in postman and works absolutely fine giving response data. I have my code below. I can't figure out what is wrong and how to solve it. Any help would be appreciated. Thanks in advance.
import React,{useState} from 'react';
export default function SearchCity(){
const[query,setQuery] = useState('');
const[weatherResponse,setWeatherResponse] = useState([]);
const searchCity = async (e) =>{
e.preventDefault();
const api_key ="YourApiKey";
const url = `https://api.weatherbit.io/v2.0/forecast/daily?city=${query}&key=${api_key}`;
try{
const res = await fetch(url);
const data = await res.json();
console.log(data.results);
setWeatherResponse(data.results);
}
catch(error){
console.error(error);
}
}
return(
<>
<form className="form" onSubmit={searchCity}>
<label className="cityTitle" htmlFor="query">City Name : </label>
<input type="text" value={query} name="query" onChange={(e)=>setQuery(e.target.value)} />
<button className="btnSearch" type="submit">Search</button>
</form>
{weatherResponse.map(res=>(
<p>{res.app_max_temp}</p>
)
)}
</>
)
}
Weatherbit 16 Day Forecast API Documentation
Weatherbit 16 Day Forecast Swagger UI
The API returns those values in property data, not result:
console.log(data.data);
setWeatherResponse(data.data);
Make sure you have a proper API key (don't post it on here of course).
Related
The bounty expires in 6 days. Answers to this question are eligible for a +50 reputation bounty.
God's Drunkest Driver wants to draw more attention to this question.
I have some code in a MERN stack app where users can enter another user's name into a search bar, and the webpage will return other properties of the user whose name they searched up.
For example, if I search up "John Doe" in the search bar, it should return something like this in the front end:
Name: John Doe
Age: 30
Sex: Male
Here is the code for the React component I made to handle this:
import React, { useState, useEffect } from "react";
import axios from "axios";
import "../../styles/styles.css";
function SearchUser() {
const [user, setUser] = useState({});
const [searchQuery, setSearchQuery] = useState("");
const [formError, setFormError] = useState(false);
async function getUsers(query) {
const response = await axios.get(`http://localhost:5000/auth/userSearch?fullName=${query}`);
setUser(response.data);
}
const handleSubmit = async (e) => {
e.preventDefault();
if (!searchQuery) {
setFormError(true);
return;
}
setFormError(false);
getUsers(searchQuery);
};
useEffect(() => {
console.log(user);
}, [user]);
return (
<div className="container">
<div className="create-profile-border">
<h1>Search a user</h1>
<form onSubmit={handleSubmit}>
<div>
<input
type="text"
placeholder="Enter a user's full name here"
onChange={(e) => {
setSearchQuery(e.target.value);
}}
value={searchQuery}
/>
{formError && !searchQuery && (
<p className="error-message">This is a required field</p>
)}
</div>
<button className="create-profile-button" type="submit">
Search
</button>
</form>
{user.fullName > 0 && (
<div>
<p>Name: {user.fullName}</p>
<p>Age: {user.age}</p>
<p>Sex: {user.sex}</p>
</div>
)}
</div>
</div>
);
}
export default SearchUser;
I have checked and confirmed that the backend code is working properly, the issue purely lies in the frontend.
The Issue I have:
After debugging and some console logging, it seems that user.fullName/user.age/user.email are all undefined. However, in this console log:
useEffect(() => {
console.log("effect[user]:", JSON.stringify(user));
}, [user]);
I get back a user object in the browser console when I type "John Doe" in the search bar:
effect[user]: {"user":{"_id":"63eea67c0316be96ebf799f0","email":"johndoe#example.com","passwordHash":"DU7fwnIlucrwT7R","fullName":"John Doe","age":"30","sex":"male","__v":0}}
I suspect there's some funny business with the rendering but as I'm still inexperienced with React, I'm not sure where to go from here. Any help would be greatly appreciated.
I subscribe to all the suggestions from phil. However, after looking at the log from your console, I think your data is returned as a user. so you should be able to get the data by setting user to response.data.user
async function getUsers(query) {
const response = await axios.get(`http://localhost:5000/auth/userSearch?fullName=${query}`);
setUser(response.data.user);
}
or
const getUsers = async (fullName) => {
setUser(
(
await axios.get("/auth/userSearch", {
baseURL: "http://localhost:5000/", // even better, use your .env file
params: { fullName },
})
).data.user
);
};
Your main issue is trying to compare the string property user.fullName to numeric 0. Unless your string is purely numeric, user.fullName > 0 will always be false.
Instead of initialising user to be an empty object, try starting it with null. Then you can more easily test if it has a value or not...
const [user, setUser] = useState(null);
// ...
{user && (
<div>
<p>Name: {user.fullName}</p>
<p>Age: {user.age}</p>
<p>Sex: {user.sex}</p>
</div>
)}
Another improvement you can make is to employ Axios' params option to correctly encode URL query parameters
const getUsers = async (fullName) => {
setUser(
(
await axios.get("/auth/userSearch", {
baseURL: "http://localhost:5000/", // even better, use your .env file
params: { fullName },
})
).data
);
};
Can you share the full JSON response from your API? I'm asking because what you pasted seems to imply the response looks something like this:
{
user: { _id: "...", email: "...", passwordHash: "..." },
_id: "63eea67c0316be96ebf799f0"
fullName: "John Doe"
age: "30"
}
Said another way... Based on your paste, the data.user object does not contain the fullName property, but rather data.fullName does.
Here I am simply making a request. The request is successful and return an array of different breweries along with cities plus more info. The useEffect does not set the default search for a new york city, instead I get a the initial array rendered from the first call.
import React, {useState, useEffect} from 'react';
import '../styles/searchPage.css'
import SearchCard from '../components/SearchCard';
const API_URL = 'https://api.openbrewerydb.org/breweries?by_city&per_page';
function SearchPage() {
const [cards, setCards] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
const searchRestaurants = async (city) => {
const req = await fetch(`${API_URL}&s=${city}`);
const data = await req.json()
console.log(data)
setCards(data)
}
useEffect(() => {
searchRestaurants('new york')
}, [])
Here is how I set up my search. I set the searchTerm onChange event to read the value typed.
Inside of my button I have an onClick function which should fire the restaurant search with any search term in it. Instead i'm receiving back the initial array that I get from the first call to api.
return (
<div className='search'>
<h1>Enter a City or Town name</h1>
<div className='search-container'>
<input
type="text"
name="search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
onKeyPress={(e) => {
if (e.key === 'Enter'){
searchRestaurants(searchTerm);
}
}}
placeholder="Search..."
class="search-input"
/>
<button
className='next'
onClick={()=> searchRestaurants(searchTerm)}
>Go</button>
</div>
Checked your code.
And checked API documentation and i found that you using API incorrectly.
I would change API_URL from https://api.openbrewerydb.org/breweries?by_city&per_page to https://api.openbrewerydb.org/
API_URL - Url defined incorrectly,you did assign endpoint url with 2 empty parameters by_city & per_page which are being sent empty.
Now to fix your issue and properly use endpoint URL should be updated.
From fetch(${API_URL}&s=${city}); to fetch(${API_URL}/breweries?by_city=${city});
Hope it helps!
I'm learning to use firebase and react. I have shared my firestore collection image. and my code for fetching the array from my document is given below.
This code is fetching the data from my firestore database and then storing the result in my watchlistMovies react state. when i try to log the react state or even data.data() it gives the desired result but when i try to map over the array or do something similar like logging watchlistMovies.myList[0].media_type it hits me with an error. i tried my best trying different things making it work but it breaks a thing or two in process.
I hope someone here will help me. Thank you in advance! : )
updated the code
const Watchlist = () => {
const [watchlistMovies, setwatchlistMovies] = useState([]);
const {currentUser} = useAuth()
const usersCollectionRef = collection(db,"users")
const docRef = doc(db,"users",currentUser.uid)
useEffect(() => {
const getWatchListMovies = async () => {
const data = await getDoc(docRef)
if (data.exists()) {
console.log(data.data());
setwatchlistMovies([...watchlistMovies ,data.data().myList])
} else {
console.log("empty");
}
}
getWatchListMovies();
}, [])
console.log(watchlistMovies);
// console.log(watchlistMovies.myList[0]);
return (
<div className="content-page-area">
<h1 className="trending-text"> My Watchlist </h1>
<Container className="watchlist-container">
<hr/>
{watchlistMovies.map(
(item) => (
<ListContent
item_poster={item.poster_url}
item_title={item.media_title}
item_year={item.release_year}
item_rating={item.media_rating}
item_type={item.media_type}
item_id={item.media_id}
/>
)
)}
</Container>
<br/>
<br/>
<br/>
</div>
)
}
export default Watchlist
I am using the TMDB API which allows me to display movies in a list.
I have my Add.js component which allows me to make a query and search for the movies and add them to my list
But I get this error:
TypeError: Cannot read property 'length' of undefined
Add.js
import React, { useState } from "react";
import { ResultCard } from "./ResultCard";
export const Add = () => {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const onChange = (e) => {
e.preventDefault();
setQuery(e.target.value);
fetch(
`https://api.themoviedb.org/3/search/movie?api_key=${process.env.REACT_APP_TMDB_KEY}&language=en-US&page=1&include_adult=false&query=${e.target.value}`
)
.then((res) => res.json())
.then((data) => {
if (!data.errors) {
setResults(data.results);
} else {
setResults([]);
}
});
};
return (
<div className="add-page">
<div className="container">
<div className="add-content">
<div className="input-wrapper">
<input
type="text"
placeholder="Search for a movie"
value={query}
onChange={onChange}
/>
</div>
{results.length > 0 && (
<ul className="results">
{results.map((movie) => (
<li key={movie.id}>
<ResultCard movie={movie} />
</li>
))}
</ul>
)}
</div>
</div>
</div>
);
};
The problem is happening at this line of code:
.then((data) => {
if (!data.errors) { // This is always giving error false since errors property is not returned from API
setResults(data.results);
} else {
setResults([]);
}
});
The returned response data is:
{status_code: 7, status_message: "Invalid API key: You must be granted
a valid key.", success: false} status_code: 7 status_message: "Invalid
API key: You must be granted a valid key." success: false
The reason for this is because the data that is returned from the API has no errors property.
You need to use data.success property instead of data.errors.
THE CODESANDBOX WORKING CODE:
https://codesandbox.io/s/issue-1ng77?file=/src/App.js
For some reason, results is undefined.
Try to console log the result after fetching data, maybe you set your data to undefined or something.
To quickly fix that, you can do something like
{results?.length > 0 && ( ... )}
I added the Nutrition file
const Nutrition = () => {
return(
<div>
<p>Label</p>
<p>Quantity</p>
<p>Unit</p>
</div>
)
}
export default Nutrition
I'm trying to map something in React but I'm getting this error map is not function. I'm trying to fetch an Api and now I'm trying to map another component to it, but the error is still there. Could someone help me or give me a hint
const ApiNutrition = () => {
const [nutritions, setNutritions] = useState([])
useEffect( () => {
getNutritions();
}, [])
const getNutritions = async () => {
const response = await fetch(`https://api.edamam.com/api/nutrition-data?app_id=${API_ID}&app_key=${API_KEY}&ingr=1%20large%20apple`)
const data = await response.json();
setNutritions(data.totalNutrientsKCal)
console.log(data.totalNutrientsKCal);
}
return(
<div>
<form className="container text-center">
<input classname="form-control" type="text" placeholder="CALORIES"/>
<button classname="form-control" type="submit">Submit</button>
</form>
{nutritions.map(nutrition => (
<Nutrition />
))}
</div>
)
}
export default ApiNutrition
From your code, I can see you have two places where you are setting the value of nutritions. One is while defining with useState(), and the other is after API call with setNutritions.
The error you are getting is map is not a function, it means somehow type of nutritions is not an array.
while defining with useState you are providing [] as default value so it means the error is with the API, the response you are getting from API which you are passing to setNutritions is not an array.
You can debug the API response type by typeof data.totalNutrientsKCal inside console.log