0

I'm not sure what's going wrong. I am importing a function that uses useState and useEffect. the function returns the variable in my state with data from a fetch call. However, when I try to map over that data, I get an error: map is not defined. My syntax looks right and this works in regular react, so I'm not sure what's going wrong now. I am getting a response back, the file is being imported/exported correctly and the state is updating (the APIKey used is hidden for this post) and pointers would be great!

code for data and updating state:

export function grabLocationData() {
  const [data, updateData] = useState([]);
  console.log("Data!", data);
  const [location, updateLocation] = useState("");
  useEffect(() => {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        console.log("lat", position.coords.latitude);
        console.log("lng", position.coords.longitude);
        const { latitude, longitude } = position.coords;
        updateLocation(`${latitude},${longitude}`);
      },
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
    );
    const url = `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${query}&location=${location}&radius=10000&key=${apiKey}`;
    console.log("console log!!!", url);
    fetch(url)
      .then((response, err) => {
        if (err) throw err;
        return response.json();
      })
      .then((responseJson) => {
        updateData(responseJson);
      });
  }, []);
  return data;
}

code for mapping

export default Locations = (props) => {
  const apiKey = "AIzaSyD3o3hDRwSZTVhlUIDOjGQ1ZqevG6fnWII";
  const data = grabLocationData();
  console.log(data);
  return (
    <ScrollView>
      {data.results.map((bank) => {
        return <View>{bank.name}</View>;
      })}
    </ScrollView>
  );
};
1
  • useState state changes are async. You are calling updateLocation in your effect. But it is still empty when you finish executing the hook. Therefore, the location part of the url will be empty when you try to do the fetch. Try splitting the code into two effects. One that sets the location. The second that fetches the json data once location is defined. Also remember to use the correct dependencies for your useEffect. React hooks docs are great place to refresh. Commented Apr 27, 2020 at 0:42

1 Answer 1

3

As @Will said in the comment, you can try to split your code into two differents effects. You will use the location state as deps for the second effect to be triggered.

export function grabLocationData() {
  const [data, updateData] = useState([]);
  const [location, updateLocation] = useState('');
  const [url, setUrl] = setState(
    `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${query}&location=${location}&radius=10000&key=${apiKey}`
  );

  // Effect triggered after the location changes
  useEffect(() => {
    // Prevent the effect to be triggered on initial render, only location's update
    if (location !== []) {
      fetch(url)
        .then((response, err) => {
          if (err) throw err;
          return response.json();
        })
        .then((responseJson) => {
          updateData(responseJson);
        });
    }
  }, [location]);

  useEffect(() => {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        const { latitude, longitude } = position.coords;
        updateLocation(`${latitude},${longitude}`);
      },
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
    );
  });

  return data;
}

I added the url as a state but since i don't know where the variables query and apiKey come from, feel free to do whatever you want with this.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.