I am trying to map the prop sizes, that I'm saving in a state when the item has been loaded from the api, but I keep getting this error: "Uncaught TypeError: can't access property "map", sizes is undefined"
const ItemDetailContainer = () => {
const { id } = useParams()
const [item, setItem] = useState({})
const [related, setRelated] = useState([])
const [sizes, setSizes] = useState([])
const [loading, setLoading] = useState(true)
const getRelated = () => {
const relatedItems = (productList.filter(product => product.category === item.category))
const clearRelated = relatedItems.filter(product => product.id !== item.id)
setRelated(clearRelated)
}
const setsizing = () => {
setSizes(item.sizes)
}
useEffect(() => {
customFetch(3000, productList.find(product => product.id == id))
.then(res => setItem(res))
.catch(error => console.log(error))
.finally(setLoading(false))
}, [])
//This is a solution to get the sizes and related items to load after the item has been loaded
useEffect(() => {
getRelated()
setsizing()
console.log(sizes);
}, [item])
return (
<>
loading ? <Spinner />
:
<ItemDetail
name={item.name}
price={item.price}
img={item.img}
stock={item.stock}
category={item.category}
description={item.description}
sizes={sizes}
related={related}
/>
</>
)
}
CodePudding user response:
There are few mistakes in usage of React hook.
1. You should not access state variable as soon as you set the state. Because value is not reliable at all.
setsizing()
console.log(sizes); // This sizes is not updated value in Reactjs.
2. You should provide correct dependencies in your hooks and can remove unnecessary functions.
In the following code, you need to add productList at least.
useEffect(() => {
customFetch(3000, productList.find(product => product.id == id))
.then(res => setItem(res))
.catch(error => console.log(error))
.finally(setLoading(false))
}, [])
3. You can write one line code to get the related list.
Here is the updated code snippet you can refer to.
const ItemDetailContainer = () => {
const { id } = useParams()
const [item, setItem] = useState({})
const [related, setRelated] = useState([])
const [sizes, setSizes] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
customFetch(3000, productList.find(product => product.id == id))
.then(res => setItem(res))
.catch(error => console.log(error))
.finally(setLoading(false))
}, [productList])
//This is a solution to get the sizes and related items to load after the item has been loaded
useEffect(() => {
if (item && productList) {
const related = (productList.filter(product => product.category === item.category && product.id !== item.id))
setRelated(related);
setSizes(item.sizes);
}
}, [item, productList]);
return (
<>
loading ? <Spinner />
:
(item? <ItemDetail
name={item.name}
price={item.price}
img={item.img}
stock={item.stock}
category={item.category}
description={item.description}
sizes={sizes}
related={related}
/> : <div>Item does not exist!</div>)
</>
)
}