0

Im new in ReactNative and I'm trying to take some data from here https://www.dystans.org/route.json?stops=Hamburg|Berlin

When I try console.log results it return full API response. I dont know why in first results.distance works and return distance, but when I'm trying to do it inside FlatList nothing is returned. Sometimes it works when i want to return only item.distance but can't somethnig like <Text>{item.stops[0].nearByCities[0].city}</Text> nowhere in my code also in console. Im getting error: undefined is not an object (evaluating 'results.stops[0]')

imports...

const NewOrContinueScreen = ({ navigation }) => {
  const [searchApi, results, errorMessage] = useDystans();

  console.log(results.distance);

  return (
    <SafeAreaView forceInset={{ top: "always" }}>
      <Text h3 style={styles.text}>
        Distance: {results.distance}
      </Text>
      <Spacer />
      <FlatList
        extraData={true}
        data={results}
        renderItem={({ item }) => (
          <Text>{item.distance}</Text>
          // <Text>{item.stops[0].nearByCities[0].city}</Text>
        )}
        keyExtractor={item => item.distance}
      />
      <Spacer />
    </SafeAreaView>
  );
};


const styles = StyleSheet.create({});

export default NewOrContinueScreen;

And here is my hook code:

import { useEffect, useState } from "react";
import dystans from "../api/dystans";

export default () => {
  const [results, setResults] = useState([]);
  const [errorMessage, setErrorMessage] = useState("");

  const searchApi = async () => {
    try {
      const response = await dystans.get("route.json?stops=Hamburg|Berlin", {});
      setResults(response.data);
    } catch (err) {
      setErrorMessage("Something went wrong with useDystans");
    }
  };

  useEffect(() => {
    searchApi();
  }, []);

  return [searchApi, results, errorMessage];
};

1 Answer 1

1

As the name implies, FlatList is designed to render a list. Your API endpoint returns a JSON Object, not an Array, so there's nothing for the FlatList to iterate. If you want to show all the stops in the list, try passing in the stops list directly.

<FlatList
    data={results.stops}
    renderItem={({ item }) => (<Text>{item.nearByCities[0].city}</Text>)}
/>

Some side notes: (1) The extraData parameter is used to indicate if the list should re-render when a variable other than data changes. I don't think you need it here at all, but even if you did, passing in true wouldn't have any effect, you need to pass it the name(s) of the variable(s). (2) The keyExtractor parameter is used to key the rendered items from a field inside of them. The stop objects from the API don't have a member called distance so what you had there won't work. From my quick look at the API response, I didn't see any unique IDs for the stops, so you're probably better off letting React key them from the index automatically.

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

7 Comments

Thanks for many clarification but also when Im trying your method I'm still getting undefined is not an object (evaluating 'item.nearByCities[0]') I dont know does it need to be converted maybe or something?
FlatList get 'undefined' maybe because results at the beginning are undefined until it download data? But after change of results it should rerender and no occur any error right? Even if there at start is undefined?
Theoretically yes, but your program is probably crashing when it reaches that error and the code stops running. Try changing the initial state to const [results, setResults] = useState({ stops: [] });
Still the same error. I don't get it how just console.log(results.distance) works fine but console.log(results.stops[0].city) do not. According to the documentation dystans.org/api.xhtml.
You need to wait until after the data is loaded from the API to try to access anything. If you look again, you'll probably see that console.log(results.distance) actually ran twice, once on first render and again when the effect completed. The first time it should have logged undefined and then worked the next time.
|

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.