简体   繁体   中英

Getting Undefined in console - React.js

So, the request is returning the JSON file. But when in console it is saying 'Undefined' and I do not know why.

So the button when clicked will send the results from my request from the google Place API; which contains the place_id needed to make the call to the Place Details API to the Info component.

const OnButtonClick = (restaurant) => {
        setRestaurant(restaurant)
        setOpenPopup(true)
    }
<button className="cardButton" onClick={() => OnButtonClick(restaurantData)}>
    View Information
</button>
<InfoPopup open={openPopup} restaurant={restaurant} onClose={() => setOpenPopup(false)} />

So, this works the way I think it does (Sorry, I am new to React)

Here's the InfoPopup component

function InfoPopup({ open, onClose, restaurant }) { 
    const [restaurant1, setRestaurant1] = useState([])

    let id = restaurant.place_id
    let URL = `/maps/api/place/details/json?place_id=${id}&key=${process.env.REACT_APP_API_KEY}`
    const fetchRestaurants1 = async () => {
        const res1 = await axios.get(URL)
        setRestaurant1(res1.data.results);
      }

    useEffect(() => {
          fetchRestaurants1()
          console.log(restaurant1) //This is getting 'Undefined' 
      }, [id]);
        

    const navigate = useNavigate()
    if (!open) {return null}
   

    return ReactDOM.createPortal(
    <>
        <div>
            {restaurant1?.map(restaurant => (
                <div key={restaurant.place_id}> {restaurant.formatted_phone_number} </div>
            ))}
        </div>
        <div className="popup">
            <div className="popup-inner">
                <button className="close-btn" onClick={onClose}> Close </button>
                <h1 className="title"> {restaurant.name} </h1>
            <ul>
                {/* <li className="service">
                    Status: {}
                </li> */}
                <li className="location">
                    Address: {restaurant.vicinity}
                    Phone Number: 
                </li>
                <li className="cost">
                    Cost: {restaurant.price_level}
                </li>
                {/* <li className="food">
                    Food Type:
                </li> */}
            </ul>
            <div className="links">
                <Link className="writeButton" to="/write" state={{data: restaurant}}>
                    Write a review
                </Link>
                {/* <button className="writeButton" onClick={() => navigate("/write", {data:restaurant})}>
                    Write a review
                </button> */}
                <Link className="readButton" to="/read" state={{data: restaurant}}>
                    Read the reviews
                </Link>
                {/* <button className="readButton" onClick={() => navigate("/read")}>
                    Read the reviews
                </button> */}
            </div>
            </div>
        </div>
    </>,
    document.getElementById('portal')
  )
}

I think the problem is on the first render, there's no ID being passed. But I do not know how to work around it. Any help would be appreciated.

Looking at this block of code:

 const fetchRestaurants1 = async () => {
    const res1 = await axios.get(URL)
    setRestaurant1(res1.data.results);
  }

useEffect(() => {
      fetchRestaurants1()
      console.log(restaurant1) //This is getting 'Undefined' 
  }, [id]);

You're awaiting the result of the GET call, which is good, because it allows you to set state in the next line after waiting for the response.

The problem: when you call fetchRestaurants1() in the useEffect(), you're not waiting for that function to execute, therefore, we jump straight to the next line and console.log() restaurant1 , which is of course still blank.

The same issue arises with set state calls. If you do:

const [value, setValue] = useState(null);

then sometime later:

setValue(5);
console.log(value);

The value posted to console will be null, because JS doesn't want to wait for the set state call to finish before moving onto the next line, console.log(value);

To fix this: make the useEffect callback async, and await the functions in which you're making your axios.get calls. Example:

  const fetchSomeData = async () => {
    const response = await axios.get(URL);
    setData(response.data);
  }

  useEffect(async () => {
      await fetchSomeData();
      /* do some stuff */
  }, []);

Of course, you still can't console.log after the set state call above.

If you want a generalizable way to log state changes without worrying about async behavior, you can add a simple useEffect:

  useEffect(() => {
    console.log(value);
  }, [value]);

Where value is any state variable. Since value is in the dependency array, anytime it changes, the useEffect will fire and log the change.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM