Why reading attributes of an object makes the object undefine? - reactjs

Below is my code, which gets data from Redux:
function ProductsDetail(props){
const dispatch = useDispatch();
useEffect( () => {
const fetch = async () => {
const {data} = await axios.get("/api/products/" + props.match.params.id);
dispatch(
{
type: "product_detail_success",
payload: data
})
}
fetch();
return () => {};
}, [])
const {product} = useSelector((state) => {
return state.productDetails
});
console.log(product)
//console.log(product.image)
return (
<div>
</div>
)
}
The console.log(product) line prints out:
However, if I don't comment out the following console.log(product.image) line, an error of Uncaught TypeError: Cannot read property 'image' of undefined will occur.
image is just an attribute of product object , why printing it on the console makes the product object undefine?
Thanks in advence!

In the initial render product is undefined so:
console.log(product) // will show nothing
//console.log(product.image)
when it re-render:
`console.log(product)` // This show what you see in you log
So try the following code:
console.log(product) // will show nothing
console.log(product?.image) // Add ? to make sure only get image when product defined

Related

How to show loader after updating data by queryClient.invalidateQueries?

In my project, I am trying to redirect to the listed page after updating an item. The code is working properly but here I am facing an issue, the loader is not working.
export const useUpdateStatusArchiveSurvey = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: updateArchiveSurvey,
onSuccess: () => {
queryClient.invalidateQueries(['searched-public-survey']);
},
});
};
By using "invalidateQueries" the updated values are displayed in the list but the loader is not working.
...
...
const {
data: queriedSurvey,
fetchNextPage: fetchNextQueries,
isLoading,
} = useListAllPublicSurvey({
query: search,
status: tab,
orderDesc: orderDesc,
actionPlanId: actionValue?.id,
});
useEffect(() => {
fetchNextQueries();
}, [queriedSurvey, search, tab, orderDesc, actionValue]);
const querySurvey = useMemo(
() =>
queriedSurvey?.pages
.map((page) => page.edges.map((edge: object) => edge))
.flat(),
[queriedSurvey, search]
);
...
...
const queryPlans = useMemo(
() =>
queriedPlans?.pages
.map((page) => page.edges.map((edge: object) => edge))
.flat(),
[queriedPlans, actionSearch]
);
const onChange = (e: any) => {
setActionValue(e);
};
console.log("isLoading", isLoading);
if (isLoading) {
return <Glimmer open={isLoading} />;
}
return (
....
....
when I console the "isLoading" at the initial call it is "true" otherwise it is "false" always.
React-query has several flags in the object returned by the useQuery hook. Note that isLoading will only be true if there is no data and the query is currently fetching. Since you already have data and you invalidated it, the stale data will be present until the refetch is complete. Use the isFetching flag to determine if a fetching is in progress regardless of having stale data or not.

Getting this error: Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))

import { useState, useEffect } from 'react';
import axios from 'axios'
function News({ pageSize }) {
const [state, setState] = useState({
article: [],
page: 1
}
)
const updateNews = async () => {
let res = await axios.get(`https://newsapi.org/v2/everything?domains=wsj.com&apiKey=79b02b430c1946cd9c505d3f91d7aec6&page=${state.page}&pageSize=${pageSize}`);
setState({ ...state, article: res.data.articles })
}
useEffect(() => {
updateNews()
}, [])
const handleNext = async () => {
setState({ page: state.page + 1 })
updateNews()
console.log(state.page);
}
let data = Array.from(state.article)
return (
<div>
<h2>News</h2>
<button onClick={handleNext}>Next</button>
{data.map((elements) => {
return (
<div key={elements.url} style={{ marginBottom: '2rem' }}>
<div> {elements.description} </div>
<div>{new Date(elements.publishedAt).toGMTString()}</div>
</div>
)
})}
</div>
);
}
export default News;
I can't display next page's data. I was able to display it when I had created multiple functions. But now as I'm trying to to clear the redundancy, I'm getting this error:
Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator)).
Pls help guys!
React state is asynchronous, so updating state & then accessing it immediately will not work. Updated state is only available on the next render cycle.
The below does not work.
setState({ page: state.page + 1 })
updateNews() // page is still old value
Best solution is to keep the currentPage in the state in a different variable & add it to the dependency array of useEffect. This would ensure every time it changes, a re-render happens with new data.
const [currentPage, setCurrentPage] = useState(0);
...
useEffect(() => {
updateNews()
}, [currentPage])
...
setCurrentPage(currentPage => currentPage + 1);

Undefined when selecting div with information

Having an issue with a piece of my code. I fetch from flask server, and display with div in React. I want to select the div and have that information pass to a new object array to return back to flask, but I keep getting undefined.
Code snippet:
function PLCPage() {
const [myjunk, setMyjunk] = useState([]);
const [devList, setDevList] = useState ([]);
const Scan = () => {
fetch('/api/home').then(response => {
if(response.status === 200){
return response.json()
}
})
.then(data => setMyjunk(data))
.then(error => console.log(error))
}
const Clear = () => {
setMyjunk({})
}
Creating the divs:
{Object.keys(myjunk).map((key) =>{
return (
<div className='plc-container' key={key} onClick={ReadStuff}>
<h1>ID:{myjunk[key]['name']}</h1>
<h1>IP:{myjunk[key]['IP']}</h1>
</div>
)
Clicking on the div, just to return a console log returns undefined.
const ReadStuff = () => {
console.log(this.IP)
}
I eventually want to return the data I have in the 2 h1 tags to a new object (devList) but I can't even get it to console log. Sorry if this is basic but I've been stumped at this for a week. Thanks
I've tried this.IP, myjunk.IP, this,myjunk.IP. myjunk['IP']. Nothing returns. And when I do myjunk.IP I get "cant read from undefined"
One way to do this is to create a separate component:
const JunkButton = ({junk}) => (
<div className='plc-container' key={key} onClick={() => ReadStuff(junk)}>
<h1>ID:{junk['name']}</h1>
<h1>IP:{junk['IP']}</h1>
</div>
)
Now your map() looks like:
{Object.keys(myjunk).map((key) =>{ <JunkButton junk={ myjunk[key] }/> }
And ReadStuff becomes:
const ReadStuff = (junk) => { console.log(junk) }
Notice how in React we explicitly pass things around as props or function parameters.
first you need to pass myjuck to function and then console it like this:
{Object.keys(myjunk).map((key) =>{
return (
// sending myjuck to function whatever that is
<div className='plc-container' key={key} onClick={() => ReadStuff(myjunk)}>
<h1>ID:{myjunk[key]['name']}</h1>
<h1>IP:{myjunk[key]['IP']}</h1>
</div>
)
ReadStuff function
const ReadStuff = (myjunk) => { console.log(tmyjunk) }

Problem accessing data of an array created from the state in Reactjs

I have an array of country codes and I need to have the name.
I am trying to access the countries data from the state (axios call) and from there filter by country code, and from that new array, extract the common name of the country.
(I am using the restcountries.com api).
-If I create a new state to map from, I get the too many re-renders.
-Right now, Although the border countries info is there, I can't access it, I get the "Cannot read properties of undefined" error, that usually is tied to a lifecycle issue, therefore I am using a condition on when to access the information.
Still I am not able to get it stable and return the name that I need.
Can someone please take a look and tell me what am I doing wrong?
Thanks in advance
import axios from "axios";
const BorderCountries = (props) => {
const [countriesList, setCountriesList] = useState([]);
useEffect(() => {
axios
.get(`https://restcountries.com/v3.1/all`)
.then((countries) => setCountriesList(countries.data))
.catch((error) => console.log(`${error}`));
}, []);
const getCountryName = () => {
const codes = props.data;
const borderCountries = [];
codes.map((code) => {
const borderCountry = countriesList.filter((country) =>
country.cca3.includes(code)
);
borderCountries.push(borderCountry);
});
// console.log(borderCountries);
if (props.data.length === borderCountries.length) {
const borderName = borderCountries.map((border) =>
console.log(border[0].name.common)
);
return borderName
}
};
return (
<div>
<h3>Border Countries:</h3>
{getCountryName()}
</div>
);
};
export default BorderCountries;
const getCountryName = () => {
const codes = props.data;
if(countriesList.length === 0) return <></>;
const borderCountries = [];
codes.map((code) => {
const borderCountry = countriesList.filter((country) =>
country.cca3.includes(code)
);
borderCountries.push(borderCountry);
});
// console.log(borderCountries);
if (props.data.length === borderCountries.length) {
const borderName = borderCountries.map((border) =>
console.log(border[0].name.common)
);
return borderName
}
};
Try this, you forgot to wait for the call to finish.

React Promise for strange API error with nested objects

I'm working with GoogleBooks API and I can get from the API the object that I need, and from there all the values I want. e.g.
console.log("item", item); // full object
console.log("title", item.volumeInfo.title); // title
but when I want to get nested objects I get an error:
console.log(item.volumeInfo.imageLinks.smallThumbnail);
TypeError: Cannot read property 'smallThumbnail' of undefined
So I created a this:
const BookItem = ({ item }) => {
const dispatch = useDispatch();
...
useEffect(() => {
const objSource = item.volumeInfo.imageLinks;
const getImages = Object.values(objSource);
console.log(getImages);
//eslint-disable-next-line
}, []);
const clickAddToStore = () => {
setAddToStore(true);
};
const clickRemoveFromStore = () => {
setAddToStore(false);
};
const addToDb = () => {
dispatch(
addToWooDb(
item.volumeInfo,
item.searchInfo,
stockQuantity,
bookStatus,
price
)
);
};
return (
<div
className="item3"
onClick={!addToStore ? clickAddToStore : clickRemoveFromStore}
>
{item.volumeInfo.title}
</div>
...
const mapStateToProps = (state) => ({
data: state.items,
loading: state.items.loading,
});
export default connect(mapStateToProps, { addToWooDb })(BookItem);
and works perfectly, hence I can see in the console:
["http://books.google.com/books/content?id=3nMEPQAAC…J&printsec=frontcover&img=1&zoom=5&source=gbs_api", "http://books.google.com/books/content?id=3nMEPQAAC…J&printsec=frontcover&img=1&zoom=1&source=gbs_api"]
0: "http://books.google.com/books/content?id=3nMEPQAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api"
1: "http://books.google.com/books/content?id=3nMEPQAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
But strangely I still get an error:
TypeError: Cannot convert undefined or null to object
I think that I can solve it with a promise, but I never understood how they work.
Any idea?
Thanks!

Resources