0

I'm new to React and Redux. I would like to ask why if I'm setting an object in a setState when I try to use it or show it in the console is undefined.

import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { Row, Col } from "react-bootstrap";
import axios from 'axios';
import ProductImage from './Sections/ProductImage';
import ProductInfo from './Sections/ProductInfo';

function DetailProduct (props){
    const productId = props.match.params.productId
    const [Product, setProduct] = useState()

    useEffect(()=>{
        axios.get('http://localhost:5000/products/'+productId)
            .then(response =>{
                setProduct(response.data)
                console.log('state '+Product._id)
            })
    }, [])

    return (

        <div className="postPage" style={{width: '100%', padding: '3rem 4rem'}}>       
            <div style={{display:'flex',justifyContent:'center'}}>
                <h1>{Product._id}</h1>
            </div>
            <br/>
            <Row gutter={[16, 16]}>
                <Col lg={12} xs={24}>
                    <ProductImage />
                </Col>
                <Col lg={12} xs={24}>
                    <ProductInfo />
                </Col>
            </Row>
        </div>
    )

}

export default DetailProduct

When the page loads it says that Product is undefined, even though it's suppose to have an object. When I console.log what response.data has it shows me the information that product would need to have. Sorry for bad english and thank you.

Jexco
  • 33
  • 4
  • setState in React is async funtion. This can provide more detail https://stackoverflow.com/questions/36085726/why-is-setstate-in-reactjs-async-instead-of-sync – Tony Nguyen Jun 05 '20 at 03:42

2 Answers2

1

The issue is that when the component renders the first time the axios request hasn't finished running. At that point, Product will be whatever you set as the default. In this case you haven't set a default for Product so it is undefined. You can do that in useState like so const [Product, setProduct] = useState({})

Another way you could solve this is wrap your component in an if statement that checks to see if Product has been set yet.

{Product && (
  <div>your component here</div>
)}
Andrew Axton
  • 1,032
  • 7
  • 9
  • It worked! Thank you very much :) can I ask what changes putting {} insise useState() ? does it initialize it with a null value ? – Jexco Jun 05 '20 at 03:50
  • it is the default value for `Product` (empty object). Let's say you were using a number and you wanted it to start at 0, it would be `useState(0)` – Andrew Axton Jun 05 '20 at 04:33
  • Can you set this as the solution if it worked for you? – Andrew Axton Jun 05 '20 at 21:08
0

buddy!

Like Tony Nguyen said that setState in React is async function. But if you want to do something when state(your Product) changed, you can set up another useEffect to do this:

useEffect(()=>{

  // Do somethings if you want to do when Product changed

}, [Product])

Please let me know, if you have any questions. :)

Clark
  • 305
  • 1
  • 8
  • For now I just want to reference it in the return function, where "{Product.id}" is, but if I understand correctly it will still be undefined it is asynced – Jexco Jun 05 '20 at 03:58
  • Maybe you need to set up initial value of your state(Produce), like this `useState({ _id: defaultID })`. – Clark Jun 05 '20 at 05:01