Oliver D
Oliver D

Reputation: 2889

How to use hooks in correct way?

I have some issue

1- I defined a function that gets data from API and calling it in useEffect, It's work well But i got this warning in VScode.

React Hook React.useEffect has a missing dependency: 'getOpenOrders'. Either include it or remove the dependency array.

2- I implement pagination in the FlatList, So when the user reached the end of data List I calling a function to increment the current page, and based on current page updated, getOpenOrders fetched again because i pass currentPage to useEffect to the dependency array

So the issue here is in getOpenOrders should be contacted previous data with the new data so I use Concat method,

It's work well But some time I got a warning tells me there an duplicated data, And when I use spread [...old, new] not work and I got a big error because Flatlist keyExtractor issue or something,

So can any hero here review my code and tell me what the wrong here with issue 1 - 2

code snippet

const OpenedAppointments = () => {

  const [openedAppointment, setOpenedAppointment] = useState([]);
  const [currentPage, setCurrentPage] = useState(1);
  const [lastPage, setLastPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [isFetch, setIsFetch] = useState(false);




 const loadMoreOrders = () => {
    if (currentPage <= lastPage - 1) {
      setLoading(true);
      setCurrentPage((prevPage) => prevPage + 1);
      console.log('loadMore??');
    }
  };

  const _renderFooter = () => {
    return loading ? (
      <View
        style={{
          paddingVertical: 10,
        }}>
        <ActivityIndicator color="#000000" size="large" />
      </View>
    ) : null;
  };
  const getOpenOrders = () => {
    let AuthStr =
      'Bearer ,,,,';

    const headers = {
      'Content-Type': 'application/json',
      Authorization: AuthStr,
    };
    Api.post(
      `/open_orders?page=${currentPage}`,
      {},
      {
        headers,
      },
    )
      .then((res) => {
        let last_Page = res.data.open_orders.last_page;
        let allOpenedOrders = res.data.open_orders.data;
        console.log('res:', allOpenedOrders);
        console.log('last_Page', last_Page);
        setLastPage(last_Page);
        setOpenedAppointment((prevOpenedOrders) =>
          prevOpenedOrders.concat(allOpenedOrders),
        ); // issue 2

        // setOpenedAppointment((prevOpenedOrders) =>[...prevOpenedOrders, allOpenedOrders]);
        setLoading(false);

    // For pull to refresh
        setIsFetch(false);

      })
      .catch((err) => console.log('err', err));
  };
// For pull to refresh
const _refresh = () => {
    setIsFetch(true);
    getOpenOrders();
  };

  React.useEffect(() => {
    getOpenOrders();
  }, [currentPage]); // warning here "issue 1"

  return (
    <FlatList
      showsVerticalScrollIndicator={false}
      contentContainerStyle={{flexGrow: 1}}
      data={openedAppointment}
      ListEmptyComponent={renderEmpty}
      renderItem={renderItems}
      keyExtractor={(item,index) => String(index)}
      ListFooterComponent={_renderFooter}
      onEndReached={loadMoreOrders}
      onEndReachedThreshold={1}

    // For pull to refresh
      onRefresh={_refresh}
      refreshing={isFetch}
    />
  );
};

export default OpenedAppointments;

Upvotes: 1

Views: 511

Answers (2)

Jan-Philipp Marks
Jan-Philipp Marks

Reputation: 1539

For Issue 1:

  • either add the dependency to the array:

    React.useEffect(() => {
      getOpenOrders();
    }, [currentPage, getOpenOrders]);
    
  • or use eslint rule as answered by @Matt Aft, It wont make a difference for your usecase

For issue 2: I would suggest removing duplicates with a Set:

   setOpenedAppointment((prevOpenedOrders) =>
      Array.from(new Set([...prevOpenedOrders, ...allOpenedOrders]))
    );

This will concat your new Orders and your old Orders with spread syntax (...) and will remove duplicates by creating a new Set. (Sets allow only unique items, therefore will remove duplicates. Then you convert it back to an Array with Array.from so you can use it as before

Upvotes: 2

Matt Aft
Matt Aft

Reputation: 8936

I think you're missing the spread operator on the second array:

setOpenedAppointment((prevOpenedOrders) =>[...prevOpenedOrders, ...allOpenedOrders]);

also issue 1 is because of the react-hooks/exhaustive-deps rule you have enabled, basically there are two ways you can fix this:

  1. wrap getOpenOrders in a useCallback and add it to the dep array in the useEffect
  2. disable the linter for that line
 React.useEffect(() => {
   getOpenOrders();
 // eslint-disable-next-line react-hooks/exhaustive-deps
 }, [currentPage]);

Upvotes: 1

Related Questions