React usestate components only show on change

Viewed 38
import React, { useState, useEffect } from "react";
import Nav from "./nav.jsx";
import axios from "axios";
import Mensbuttons from "./mensbuttons.jsx";

export default function Standort() {
  const [radius, setRadius] = useState(10);
  const [latitude, setLatitude] = React.useState("");
  const [longitude, setLongitude] = React.useState("");
  React.useEffect(() => {
    navigator.geolocation.getCurrentPosition((position) => {
      setLatitude(position.coords.latitude);
      setLongitude(position.coords.longitude);
    });
  }, []);
  function handleClick() {
  setLongitude()
  }

  const [posts, setPosts] = useState([]);
  useEffect(() => {
    axios
      .get(
        "https://openmensa.org/api/v2/canteens?near[lat]=" +
          latitude +
          "&near[lng]=" +
          longitude +
          "&near[dist]=" +
          radius
      )
      .then((res) => {
        setPosts(res.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  return (
    <>
      <Nav />
      <div class="header">
        <h1>Mensen in der Nähe</h1>
      </div>
      <button onClick={handleClick(2)}>2</button>
      {posts.map((list) => {
        return <Mensbuttons name={list.name} id={list.id} />;
      })}
    </>
  );
}

Hello guys so I have a method where I want to show nearby canteens. I do this by getting the current koordinates and passing them as a varible into the Url of the api. The Problem is the buttons of the canteens only show up when I change something at the code. So I probably have to rerender it. But if I try to do it with a button method. Nothing shows up probably because there too many rerenders.(I think that because this shows in the console) I hope you can help me

2 Answers

Your onClick handler should be a function, not a function call.

Instead of

<button onClick={handleClick(2)}>2</button>

use

<button onClick={() => handleClick(2)}>2</button>

I believe you haven't defined the useEffects correctly.

I reduced longitude and latitude states to a single coordinates state. which is initialized as null.

  const [coordinates, setCoordinates] = React.useState(null);

Which in the very first render is set to true coordinates:

    React.useEffect(() => {
    navigator.geolocation.getCurrentPosition((position) => {
      setCoordinates(position.coords);
       
    });
  }, []);

Now make the second useEffect run only after the coordinates has changed:

    useEffect(() => {
  if (coordinates) { // Don't let it make get request if it is null.
    const { latitude, longitude } = coordinates;
    axios
      .get(
        "https://openmensa.org/api/v2/canteens?near[lat]=" +
          latitude +
          "&near[lng]=" +
          longitude +
          "&near[dist]=" +
          radius
      )
      .then((res) => {
        setPosts(res.data);
      })
      .catch((err) => {
        console.log(err);
      });
  }
}, [coordinates]);

And, I don't think this button is needed anymore:

      <button onClick={handleClick(2)}>2</button>

Final Code:

import React, { useState, useEffect } from "react";
import Nav from "./nav.jsx";
import axios from "axios";
import Mensbuttons from "./mensbuttons.jsx";

export default function Standort() {
  const [radius, setRadius] = useState(10);
  const [coordinates, setCoordinates] = React.useState(null);

  React.useEffect(() => {
    navigator.geolocation.getCurrentPosition((position) => {
      setCoordinates(position.coords);
    });
  }, []);

  const [posts, setPosts] = useState([]);
  useEffect(() => {
    if (coordinates) {
      // Don't let it make get request if it is null.
      const { latitude, longitude } = coordinates;
      axios
        .get(
          "https://openmensa.org/api/v2/canteens?near[lat]=" +
            latitude +
            "&near[lng]=" +
            longitude +
            "&near[dist]=" +
            radius
        )
        .then((res) => {
          setPosts(res.data);
        })
        .catch((err) => {
          console.log(err);
        });
    }
  }, [coordinates]);

  return (
    <>
      <Nav />
      <div class="header">
        <h1>Mensen in der Nähe</h1>
      </div>
      {posts.map((list) => {
        return <Mensbuttons name={list.name} id={list.id} />;
      })}
    </>
  );
}
Related