I'm looking to figure out what I'm doing wrong here however i'm not entirely sure. I am looking to pass down an object from the site, which is 'colour' as per the database (Australian).
I then want to map this array to the front end to only display these colours as such. E.g this array has ["White", "Black", "Red"] etc.
Initially I have a useEffect function, as below:
useEffect(() => {
const getProduct = async () => {
try {
const res = await publicRequest.get("/products/find/" + id);
setProduct(res.data);
} catch {}
};
getProduct();
}, [id]);
From this, I am attempting to map:
<Filter>
<FilterTitle>Colour</FilterTitle>
{product.color.map((c)=> (
<FilterColour color={c} key={c}/>
))}
</Filter>
But I receive the classic:
TypeError: Cannot read properties of undefined (reading 'map')
I've tried both colour, color etc, but cannot resolve? Any ideas Stack!
Before it calls setProduct your default value should have color as its property and it needs to be an array. If you're facing this after setProduct is called just check res.data to see if you're getting data in the format you expected.
Since the data you are attempting to render is the result of an asynchronous function, product is still not populated during the initial render, it gets populated only after.
What we usually do in React to circumvent this, is adding conditional statements.
This should do the trick -
<Filter>
<FilterTitle>Colour</FilterTitle>
{product.color && product.color.map((c)=> (
<FilterColour color={c} key={c}/>
))}
</Filter>
You need to make sure the attribute that you want to access keeps the same data structure. If not, you need to check whether it is undefined or not.
Solution 1:
Keep the same data structure. The useState hook should be initialized as:
const [product, setProduct] = useState({color: []})
// or populate other attributes in the initial state.
Solution 2:
Check if the data exists:
{product.color && product.color.map((c)=> (
<FilterColour color={c} key={c}/>
))}
Related
I am building my first react app for my final react course on scrimba and I am retrieving data from an API and setting a part of the data to an array set in state, but I cant seem to access a property of the array
import React from 'react'
const [request, setRequest] = React.useState([])
React.useEffect (() => {
fetch('https://opentdb.com/api.php?amount=5')
.then(res => res.json())
.then(data => setRequest(data.results.map(({ question, correct_answer, incorrect_answers }) => ({question, correct_answer, incorrect_answers}))))
}, [])
console.log(request[0]) // returns the first object array
console.log(request[0]["question"]) // gives an error
console.log(requst[0].question) // gives an error
<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>
but I cant seem to access a property of the array
Sure you can, but only when that array element exists. The initial state of the array is empty:
const [request, setRequest] = React.useState([])
An empty array has no elements, so this logs undefined to the console:
console.log(request[0])
And then this produces an error:
console.log(request[0]["question"])
And then this does not produce an error, because it isn't executed, because the line before it produced an error:
console.log(requst[0].question)
But if that line of code was executed, it too would produce an error.
The data you're fetching to populate state is coming from an asynchronous operation. So it's going to happen at some later time. (Could be milliseconds and feel instantaneous, but still some later time.)
Until that data has been fetched and until the state has been updated, the code needs to be able to handle the initial state of the empty array. Optional chaining is one option:
console.log(requst[0]?.question)
Or perhaps wrapping the whole thing in a conditional:
if (request.length > 0) {
console.log(request[0]);
console.log(request[0]["question"]);
console.log(requst[0].question);
}
How you prefer to handle an empty array is up to you and the logic you're implementing. But the point is that since you define an empty array, the code should expect to start with an empty array.
Setting data inside request state takes time. So you always get undefined for the first log of console.log(request[0]) and error for other two console.logs.
In that case, you can check by using UseEffect hook.
useEffect(() => {
if(request.length === 0) return;
console.log(request[0]); // returns the first object array
console.log(request[0]['question']);
console.log(requst[0].question);
}, [request]);
If you don't want to use useEffect, you can use ? to access object properties without error.
console.log(request[0]);
console.log(requst[0]?.question);
if (request !== undefined && request.length > 0) {
console.log(request[0])
console.log(request[0]["question"])
console.log(request[0].question)
}
Hope you're all doing good, I've tried looking around for a specific answer regarding this issue I'm having in ReactJS where I'm trying to map over an array I'm fetching via my local system and I keep getting this error in the console:
TypeError: null is not an object (evaluating 'daysData.map')
Here is a snapshot of my bit of code where I'm initializing the array from fetch:
And here it is in text format:
// Here I initalize the array with useState
const [daysData, setDaysData] = useState(null);
// Here is the port I'm fetching my array from.
useEffect(() => {
fetch('http://localhost:5001/chocolates')
.then((resp) => resp.json())
.then((data) => setDaysData(data));
}, []);
// Console logging is sending back the array with no issues
console.log(daysData);
And here is the map function where I'm trying to render a with the 'id' key from the array:
Here is the bit of code in text format:
{/* Here I'm getting the error " TypeError: null is not an object (evaluating 'daysData.map') " */}
{daysData.map((day) => (
<div>{day.id}</div>
))}
And here is an example of the array where I've fetched data from in which I'm trying to map over:
Thanks for any help in advance
Just set the default state to an empty array instead of null so the Array.prototype.map() works on the initial render before the data is received.
The map() of the empty array won't produce anything in the rendered view
const [daysData, setDaysData] = useState([]);
Your array is null on rendering, and your api fetches after rendering your web app so you need to set it conditionally like this
{daysData !== null? daysData.map((day) => <div>{day.id}</div>:null)}
im having problems with this line:
useEffect(() => {
if (AplicationsList) {
setDetail({ ...Detail, components: AplicationsList });
}
}, [AplicationsList]);
When AplicationsList its an empty array [] it gives me an error, like Detail is then undefined. But when its not empty works fine...
either if the array its empty or not I have to set the value on components attribute of Detail.
Any idea why this is happening?
This is the error I'm facing in the child component that depends on "Detail" passed as props:cannot read property map of undefined
And I get this react warning:
can't perform a react state update in an unmounted component
I've tried with this functional update but still is giving me the same errors:
setDetail(Detail => ({
...Detail,
components: AplicationsList,
}));
From you question, I understand Details is an object and AplicationsList is an array.
I think you have set the state of details this way or similar to this
const [Details, setDetails] = useState();. The problem with this is the initial value of Details is undefined and you are trying to destructure undefined. Instead set it as const [Details, setDetails] = useState({});
In useEffect you are checking if AplicationsList is empty, but if(AplicationsList) return true even for empty array. So check for the length instead, if(AplicationsList.length > 0)
Suggestion: It's good practice to have the state variable name to be of lowerCase and follow camleCase format to name variable. Instead of Details and ApplicationsList, its good you rename to details and applicationsList.
In React component I have a state called projectTypes which is an array of objects:
const [projectTypes, setProjectTypes] = useState([])
This state is set inside an useEffect hook:
useEffect(() => {
...
setProjectTypes(...)
...
})
with information received from a fetch to the server. That information is displayed inside a table and everything is working as expected.
I want to check a field inside the first element (an object) of the state array:
projectTypes[0]._id
To be sure that I'm accessing projectTypes when it already has values, I'm using another hook:
useEffect(() => {
...
console.log(projectTypes[0]);
console.log(projectTypes[0]._id);
...
}, [projectTypes]);
I have 2 questions:
Is this the right procedure to be sure that when accessing the state it already has values inside: creating a new hook with [projetTypes] as the 2nd parameter?
Inside this second hook, if I only use the first console.log - console.log(projectTypes[0]) - everything works as expected and the first object of the state is printed to the console with an _id field. But using the second one - console.log(projectTypes[0]._id) - results in an error: "TypeError: Cannot read property '_id' of undefined". Why can I access the object inside the state array just fine, and print it with all its fields, but if I try to access one of its fields, I get an error?
As the effect is called whenever any of its dependencies update, You can do it with as single effect.
within the effect, check if data within it is valid, if yes, do something, else continue.
like
useEffect(() => {
if(projectTypes && projectTypes.length >0){
//do something
}
}, [projectTypes]);
I'm using OpenWeatherAPI and React to make a weather app for practie, I'm able to retrieve my date data, but my temp data is giving some issues and I'm not totally sure why. Here is my error:
Uncaught TypeError: Cannot read property 'temp' of undefined
at Weather.js:31
Here is my Weather.js:
componentDidMount () {
axios.get('http://api.openweathermap.org/data/2.5/forecast?q=London,uk&appid=APIKEY')
.then(response => {
this.setState({forecasts: response.data.list});
});
}
render() {
const projections = this.state.forecasts.map(forecast => {
return <Subweather
date={forecast.dt_txt}
temp={forecast.main.temp}
key={forecast.id} /> ;
});
const weather = projections[0, 8, 16, 24, 32];
return (
<div className={classes.WeatherDiv}>
{weather}
</div>
Here is what the array looks like when I return it in the console (image attached).
I assumed that since I am mapping this to a new array, the best way to get this value is to use forecast.main.temp since the temp value is within the main but this obviously comes back as undefined so it's not there.
What am I missing here?
forecast is an array, so you need to access its elements. main is a property of each object belonging to this array. You may need to loop through each element to get all the data you need, but for retrieving the first entry you need to access the array element itself before main can be referenced:
var myTemp = forecast[0].main.temp;
Well the answer to your error is the asynchronous api call that you make in componentDidMount().
React doesn't guarantee to hold render() from being executed till the api call returns a response and hence your forecasts in state is undefined when render() is executed.
What I suggest is to rather set an initial default state for forecasts in your component so that it renders without any error. And once you receive the response in componentDidMount() your component will anyhow be re-rendered due to setState().