Je construis une application avec React Native en utilisant expo et j'ai implémenté Redux. Maintenant, dans mon composant, j'ai besoin de récupérer des éléments d'une API pour remplir une liste. J'ai décidé d'utiliser le hook useEffect pour y parvenir. Maintenant, dans le tableau de dépendances de mon hook useEffect, j'ai mis ma liste d'états Redux. Comme ça:

const onFetchOrders = async (query: string, offset: number, limit?: number, filter?: {}) => {
  await props.fetchOrders('', 0);

}

useEffect(() => {
  setIsLoading(true);
  onFetchOrders('', 0);

  if (props.orders.length > 0) {
    setOrders(props.orders)
  } else {
    setIsLoading(true);
  }

}, [props.orders])

Les commandes sont mappées aux accessoires dans un autre composant:

const mapState = (state : RootState) => ({
    orders: state.orders.items,
    debtor: state.debtor.debtor,
    totalCount: state.orders.totalCount
})

const mapDispatch = (dispatch: any) => {
    return {
      fetchOrders: (query?: string, offset?: number, limit?: number, filters?: {}) => dispatch(tFetchOrders(query, offset, limit, filters)),
      fetchDebtor: (uuid: string) => dispatch(thunkFetchDebtor(uuid)),
      fetchCredentials: () => dispatch(thunkFetchCredentials()),
    };
  }

//const connector = connect(mapState, mapDispatch)(Root);
export const connector = connect(mapState, mapDispatch);

export type OrdersProps = ConnectedProps<typeof connector> & OrderStackNavProps<"Orders">;

Maintenant, si je lance l'application, mon hook useEffect est constamment renvoyé car il semble y avoir une mise à jour dans le tableau des commandes.

0
stefan0905 31 août 2020 à 13:02

2 réponses

Meilleure réponse

La façon dont vous avez écrit votre hook useEffect, il s'exécutera à chaque fois que le props.orders changera, car vous avez passé cet accessoire dans le tableau comme argument optionnel. Pour en savoir plus sur le fonctionnement de useEffect, consultez la documentation ReactJS ici.

Si vous souhaitez que votre hook useEffect ne s'exécute qu'une seule fois lors du rendu du composant, vous devez passer un tableau vide:

useEffect(() => {
  setIsLoading(true);
  onFetchOrders('', 0);
}, []);

Une fois que vous avez lancé votre récupération, vous pouvez ajouter les commandes aux accessoires dans un autre crochet useEffect:

useEffect(() => {
  if (props.orders.length > 0) {
    setIsLoading(false);
    setOrders(props.orders)
  } else {
    setIsLoading(true);
  }

}, [props.orders])
1
p-syche 31 août 2020 à 10:53

UseEffect s'exécute à chaque fois que des accessoires sont modifiés dans le composant. Pour éviter cela et avoir toujours des commandes dans votre tableau useEffect, vous pouvez utiliser déstructuration de la syntaxe des affectations

const { orders } = props // where the magic happens

useEffect(() => {
  setIsLoading(true);
  onFetchOrders('', 0);

  if (orders.length > 0) {
    setOrders(orders)
  } else {
    setIsLoading(true);
  }

}, [orders])

Ce code ne fonctionnera désormais que chaque fois que le prop des commandes change et non lorsque l'un des autres accessoires change.

En outre, si vous oubliez de le mentionner, consultez problème de boucle infinie useEffect . Vous pouvez combiner votre hook useEffect et useCallback pour éviter les boucles infinies.

Enveloppez la fonction que vous souhaitez passer dans le hook useEffect avec le hook useCallback. Appelez ensuite la fonction encapsulée dans le hook useEffect. Cela évitera une boucle infinie dans votre useEffect.

const loadCustomers = useCallback(async (query: string, offset: number, limit?: number, filter?: {}) => {
    await props.fetchOrders('', 0);
    ...
}
0
Marcus Melodious 31 août 2020 à 11:17