Home > Software engineering >  how to prevent keep getting duplicated result from API with Flatlist react native?
how to prevent keep getting duplicated result from API with Flatlist react native?

Time:11-27

im trying to get repos in order of stars from the API, but as i scroll, i keep getting random duplicates :

export default function App() {
  const [repos, setRepos] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const getUsers = async () => {
      const res = await axios.get(
        `https://api.github.com/search/repositories?q=created:>2020-01-01&sort=stars&order=desc&page=${page}`
      );
      const data = await res.data;
      // setRepos([...repos, ...data.items]);
      setRepos([...repos, ...data.items]); 
      setLoading(false);
      };
      getUsers();
    }, [page]);

    const scrollToEnd = () => {
      if (loading === false) {
        setPage(page   1);
        setLoading(true);
      }

      console.log("page", page);
    };

    const renderItem = ({ item }) => (
      <Text className="boxed">
        Stars: {item.stargazers_count} Id: {item.id}
      </Text>
    );

    return (
      <SafeAreaView style={styles.screen}>
        <View style={styles.container}>
          <FlatList
            data={repos}
            renderItem={renderItem}
            keyExtractor={(item) => item.id}
            onEndReached={scrollToEnd}
            showsVerticalScrollIndicator={false}
          />

          {loading && <Text className="loading">...loading</Text>}
        </View>

        <StatusBar style="auto" />
      </SafeAreaView>
    );
  }

CodePudding user response:

I think you got too much going on in your useEffect function, maybe missing a closing }. Try this:

function App() {
  const [repos, setRepos] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(true);

  // This will trigger when page changes:
  useEffect(() => {
    getUsers();
  }, [page]);

  const getUsers = async () => {
    const res = await axios.get(
      `https://api.github.com/search/repositories?q=created:>2020-01-01&sort=stars&order=desc&page=${page}`
    );
    const data = await res.data;
    // setRepos([...repos, ...data.items]);
    setRepos([...repos, ...data.items]);
    setLoading(false);
  };

  const scrollToEnd = () => {
    if (loading === false) {
      setPage(page   1);
      setLoading(true);
    }

    console.log("page", page);
  };

  const renderItem = ({ item }) => (
    <Text className="boxed">
      Stars: {item.stargazers_count} Id: {item.id}
    </Text>
  );

  return (
    <SafeAreaView style={styles.screen}>
      <View style={styles.container}>
        <FlatList
          data={repos}
          renderItem={renderItem}
          keyExtractor={(item) => item.id}
          onEndReached={scrollToEnd}
          showsVerticalScrollIndicator={false}
        />

        {loading && <Text className="loading">...loading</Text>}
      </View>

      <StatusBar style="auto" />
    </SafeAreaView>
  );
}

export default App;

CodePudding user response:

You should avoid duplicate data before set it to state, update your getUsers function with this,

useEffect(() => {
const getUsers = async () => {
  const res = await Axios.get(
    `https://api.github.com/search/repositories?q=created:>2020-01-01&sort=stars&order=desc&page=${page}`,
  );
  const data = await res.data;
  let arrRepos = [...repos, ...data.items];
  let uniq = new Set(arrRepos.map((objRepo) => JSON.stringify(objRepo)));
  arrRepos = Array.from(uniq).map((objRepo) => JSON.parse(objRepo));
  setRepos(arrRepos);
  setLoading(false);
};
getUsers();
}, [page]);
  • Related