I have this component, which works fine, but only once. If I reload, I have a undefined error.
My component :
import { UidContext } from "../components/AppContext"
import React, { useContext, useEffect, useState } from "react"
import axios from "axios"
export default function Balance() {
const uid = useContext(UidContext)
const [userWallet, setUserWallet] = useState(null)
useEffect(() => {
if (uid !== null) {
axios.get(`${process.env.REACT_APP_API_URL}api/balance/${uid}`)
.then((res) => setUserWallet(res.data[0]))
}
}, [uid])
return (
<section>
{userWallet.salaire1}
</section>
)
}
The result at first load :
userWallet result
and then, I have this error :
TypeError: Cannot read property 'salaire1' of null
Why would a console.log work, and not in the JSX ?
Thank you
You can use optional chaining with userWallet?.salaire1 . or handle with ternary conditional like
userWallet.salaire1 && userWallet.salaire1
In this case you have predefined state value userWallet is null. hence the UI couldn't render undefined property therefore your screen is blank and promp error
actually your console work but it the log return twice, the first one is null then the data shown.
I hope my answer can help to understand your issue :)
Related
I am sending AllmightyUID = 2(for example) from App.js in the User.js component through contextApi ,there is no useEffect in my User component , but when i log the value in my User component it is logged 2 times first time is shows undefined and second time correct data(2) even if i log it after 2- 3 seconds due to this i am unable to make further api calls (i get cannot read the value undefined errors)
solutions i have tried :-
1.) I have removed strict mode from index.js
2.) passed the value as props but still the same problem
import React, { useContext, useState } from 'react'
import { AllMightyUID } from '../App'
import axios from 'axios'
const User = (props) => {
let receivedUID = useContext(AllMightyUID)
const [UID1, setUID1] = useState();
setTimeout(() => {
console.log(receivedUID);
}, 2000);
return(
<></>
)
}
I am sending data from a state variable in App.js
Often, API calls are asynchronous by nature, meaning the rest of the code can execute while the app is still waiting for the API response. Which explains why you get the value when you use the setTimeout function.
You can try to have an if statement that will make other API calls after the UID has been set.
Before rendering it's called that's why you got the error.
You should try to in useEffect and then you solved your issue.
import React, { useContext, useState, useEffect } from 'react'
import { AllMightyUID } from '../App'
import axios from 'axios'
const User = (props) => {
let receivedUID = useContext(AllMightyUID)
const [UID1, setUID1] = useState();
useEffect(() => {
console.log(receivedUID);
}, []);
return(
<></>
)
}
I have a react component that gets data from an API end point. For the purposes of debugging when I call the API I log the result of the API call to the console and it looks like this:
The problem I have is that when I try to render the BreadCrumbLinks Property in my component I get this error:
TypeError: Cannot read properties of undefined (reading 'map')
at BreadCrumbHeader
I am getting an "Undefined" error, but I know that the data is present because I can read and render all of the other fields (for example BreadCrumbBgImage).
Also, if I comment out the map/loop the rest of the data is displayed correctly when the page loads. Then if I uncomment it out and save the file the data for the map/loop now shows correctly.
I can only assume that the code is trying to render the contents of the loop before it has been loaded.
This is what the code for the component looks like:
import React, { useState, useEffect } from 'react';
import API from "../../API";
import { useLocation } from 'react-router-dom';
import { BreadCrumbTitleSection, SubtitleSection, Subtitle } from './breadCrumbHeaderStyle';
import { Breadcrumb } from 'react-bootstrap';
function BreadCrumbHeader() {
const location = useLocation();
const [breadCrumbData, setBreadCrumbData] = useState([]);
const getBreadCrumbData = async () => {
const breadCrumbHeaderResponse = await API.fetchBreadCrumbHeader(location.pathname);
setBreadCrumbData(breadCrumbHeaderResponse);
console.log("OUT-PUT-OF-API-CALL");
console.log(breadCrumbHeaderResponse);
console.log("END-OF-OUT");
};
useEffect(() => {
getBreadCrumbData();
}, [location.pathname]);
return (
<div>
<BreadCrumbTitleSection backgroundUrl={breadCrumbData.BreadCrumbBgImage}>
<div className="container">
<div className="row no-gutters">
<div className="col-xs-12 col-xl-preffix-1 col-xl-11">
<h1 className="h3 text-white">{breadCrumbData.BreadCrumbTitle}</h1>
<Breadcrumb>
{breadCrumbData.BreadCrumbLinks.map(breadCrumbLink => (
<Breadcrumb.Item href={breadCrumbLink.LinkUrl} key={breadCrumbLink.Id} active={breadCrumbLink.IsActive}>
{breadCrumbLink.LinkText}
</Breadcrumb.Item>
))}
</Breadcrumb>
</div>
</div>
</div>
</BreadCrumbTitleSection>
<SubtitleSection>
<Subtitle> {breadCrumbData.SubTitle}</Subtitle>
</SubtitleSection>
</div>
);
}
export default BreadCrumbHeader;
Can anyone explain what is going on here and how I can solve i?
You are trying to map data before its fetched, so its an empty array (initial value of breadCrumbData state). You should use optional chaining:
{breadCrumbData?.BreadCrumbLinks?.map(breadCrumbLink =>
You are tryng to map your array before the state change, the useEffect is called on first render, your array don't have the state in the first render, you can use something like a loading hook, like this
const [loading, setLoading] = useState(false)
useEffect(() =>{
setLoading(true)
fetchData()
},[])
const fetchData = () =>{
//my api call
setLoading(false)
}
return (
{loading ? (
// my loading message or function
): (
// my show component
)}
)
this is a just an litle example how you can do
I have a table in my database cold Apoet in my table field could name so I try to bring the name from the database but when I run the app this message appear
undefined is not an object (evaluating abc.name)
below my code
import React from 'react';
import {useEffect} from 'react';
import {useState} from 'react';
import { useRoute } from '#react-navigation/native';
import { DataStore } from 'aws-amplify';
import { Apoet } from '../../models';
const ProductScreen = () => {
const route = useRoute();
console.log(route);
const {abc, setABC}= useState<Apoet | undefined>(undefined);
useEffect (()=>{
if(!route.params?.id){
return ;
}
DataStore.query(Apoet,route.params.id).then(setABC)
},[route.params?.id]);
return (
<View>
<Text>{abc.name} </Text>
</View>
)}
Your useState is wrong, change with square brackets. Also be sure route changes as you expect otherwise it will be undefined again since your initial state value is also undefined
const [abc, setABC] = useState<Apoet | undefined>(undefined);
Issues
You've incorrectly accessed the return value from the useState hook, it returns an array, not an object.
const {abc, setABC} = useState<Apoet | undefined>(undefined);
You also use an undefined initial value, so attempting to access into it will throw an error.
Solution
Fix the return and use array destructuring assignment and use a valid initial value.
const [abc, setABC] = useState<Apoet>({});
...
<Text>{abc.name}</Text>
abc is now defined and can access a name property that will be undefined util the state is updated.
Or if you want to keep it allowed to be undefined, use a null check or Optional Chaining operator on the name property access.
Example:
const [abc, setABC] = useState<Apoet | undefined>();
...
<Text>{abc && abc.name}</Text>
or
<Text>{abc?.name}</Text>
I have a problem with reading {find}.
The problem is in ProductDetail.js.
First, click on the products link than on any product to see details.
TypeError: Cannot read properties of null (reading 'find')
https://codesandbox.io/s/react-router-product-detail-pages-dynamic-links-forked-y1o0n?file=/src/ProductDetail.js:418-429
You've done some mistakes over there in your ProductDetail.js file.
First:
You can use useEffect hook to check and compare if there is a matching id or not.
Second:
You can use useState hook to store the thisProduct and update the thisProduct value by calling setThisProduct and use it in the JSXElement.
This is always a best practice to use the state for data set and get.
Here is more about React.Hooks
Third:
Price is a Object and you can't render your object like that, so use the key instead of object while rendering. like this: {thisProduct?.price?.current?.value}
You can learn more about optional chaining
Fourth:
productId which you're getting from useParams is a string type, and your productId from sneakers is a number type. So you need to change your productId to number while comparing like this: Number(productId)
Learn about Numbers in Js
Here is the complete code of yours:
// ProductDetail.js
import React, { useContext, useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { StateContext } from "./GlobalContext";
function ProductDetail() {
const { productId } = useParams();
const { sneakers } = useContext(StateContext);
const [thisProduct, setThisProduct] = useState({});
useEffect(() => {
if (sneakers) {
const findProduct = sneakers.find((product) => {
return product.id === Number(productId);
});
console.log("findproduct", findProduct);
setThisProduct(findProduct);
}
}, [productId, sneakers]);
return (
<div>
{thisProduct && (
<>
<h1>{thisProduct?.name}</h1>
<p>Price: {thisProduct?.price?.current?.value}</p>
<p>{thisProduct?.description}</p>
</>
)}
</div>
);
}
export default ProductDetail;
completely check your state and props, it is not providing valid data to child component
<StateContext.Provider value={{ sneakers }}>
{console.log(sneakers, "== thisProduct")}
{children}
</StateContext.Provider>
console will show your data, it coming null so that is the issue
I am trying to render data which is comming from nodejs api I am using redux for state management.
The problem is When i try to map over the data it gives me error saying this.
Uncaught TypeError: Cannot read property 'map' of undefined
This is my code /home.js
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {getArticle} from '../../redux/actions/article';
class Home extends Component {
componentDidMount() {
this.props.getArticle();
}
render() {
console.log(this.props.article.article);
return (
<div>
{this.props.article.article.data.map(val => console.log(val)) }}
</div>
);
}
}
const mapStateToProps = state => ({
article: state.article
});
export default connect(mapStateToProps, {getArticle})(Home);
this is the log when i run this.props.article.article
This is happening because you didn't set any default value for article in redux, Because of which when your component renders first, article is empty and that's why map throws an error.
By doing this, you are ensuring that this.props.article.article.data is defined or not. if that is defined then only this.props.article.article.data.map(val => console.log(val)) your map() executes and console.log the value, but if that is not defined it simply do nothing.
Can you please try using this:
return (
<div>
{this.props.article.article.data && this.props.article.article.data.map(val => console.log(val)) }}
</div>
);
Its because, the component is trying to render before the network call is done.
Before we map through, we check id the article data is available. Try this to out:
return (
<div>
{this.props.article.article.data? this.props.article.article.data.map(val => console.log(val)):'Loading' }
</div>
);