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]);
Related
im building crypto wallet in reactjs and then i will make it in tauri but what im tryng to do now is to read mnemonic from text file but i get this error img
the code is this:
fetch(raw)
.then(r => r.text())
.then(text => {
console.log(text); // console logs output
});
const [computer] = useState(
new Computer({
mnemonic: (text), // i want here to be output but i get that error
There are a couple problems here. The initial problem, and the reason the error occurred, is because the text variable is out of scope when you are calling it inside the useState hook. You will need to set the state value when you have reference to the text variable.
The second problem is that you are wanting to set the initial value of the a state in a react component based off an asynchronous query. Since an asynchronous value cannot be available at the initial render, you need to combine the useState hook and the useEffect hook to set the value after the initial load.
With such limited code shown, i will try to fill in the gaps and make an example of what i think you are looking for:
function Component() {
const [computer, setComputer] = useState("");
useEffect(() => {
fetch(raw).then(r => r.text()).then(text => {
setComputer(new Computer({ mnemonic: text }))
})
}, [])
return (
// whatever you render
)
}
This way, at render your component will have a default value of "" and then when the async fetch call has finished it will update the value. If you pass an empty array as the second parameter to the useEffect hook, it will only be called on the initial render.
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)
}
I get data from localstorage.
I used useEffect. But when I want to get a value in object, I got problem.
const [carinfo, setCarInfo] = useState();
useEffect(() => {
const storedData = JSON.parse(localStorage.getItem("carData"));
setCarInfo(storedData);
console.log(storedData.brand);
}, []);
console.log(carinfo.brand);
console.log(storedData.brand) is working.
No console.log(carinfo.brand) is not working
I have this error
Uncaught TypeError: Cannot read properties of undefined (reading 'brand')
I suspect you get the error because the effect hasn't happened yet. The first time your component renders, carinfo is undefined.
You can set an initial value to state to get around this:
const [carinfo, setCarInfo] = useState({});
Your console.log(carinfo.brand) is getting executed before the useEffect.
That means you're trying to access the value of carinfo before setting it.
Sol 1: Put the console.log(carinfo.brand) inside useEffect
Sol 2: If you need the carinfo outside useEffect, write it inside a function and call that function after setting the carinfo value
On your initial render, the value of carinfo will match what you call useState with.
useState() is the equivalent of useState(undefined). undefined is a value without a brand property.
useEffect will fire and then update the state with whatever value you have in localStorage, given that it matches your expected data structure (you may want to consider creating a safer way get to localStorage.
Nevertheless,only after the initial render is the state set, and then you may have the expected value in carinfo.
You can use optional chaining to protect yourself, console.log(carinfo?.brand) or some other way to handle the undefined case.
The other answers cover the reasons of the Exception, this is just the simplest fix:
console.log(carinfo?.brand);
I'm writing my first hook and I also use redux.
I'm listening to orientation sensor data from the mobile device in React native and when it updates I filter it to see if the new value is different than the old value before I send it over to redux state to be stored.
I'm noticing in the filterData method the data is always null. But if I console log the storedVal in the render I see it's always being updated and it's updated in the Redux store as well.
But for some reason filterData only has access to the initial value and doesn't get the updated values. Any idea how to fix this?
const storedVal = useSelector(selectors.selectStoredVal);
const filterData = useCallback(
() => {
console.log(storedVal);
},
[storedVal]
);
useEffect(
() => {
orientation.pipe(filter(filterData)).subscribe((data) => {
console.log('Data filtered correctly, new data received here');
}
}
),
[];
}
An empty dependency array for useEffect means that the callback function within it will only run once (on component mount).
useCallback is creating a function that is being passed into the filter function. Because storedVal is a dependency for filteredData, went storedVal changes and filteredData is updated to a new function, your useEffect still has a reference to it's old value.
Try adding [filteredData] to your dependency array for the useEffect.
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.