admin管理员组

文章数量:1196136

I am using a useEffect hook to make an API call depending on data from a photos prop being passed in.

const ImageCarousel = ({ src, photos }) => {
  const [photoList, setPhotos] = useState([]);
  const storageRef = firebase.storage().ref();
  console.log("photos prop:", photos);

  const getImage = photoId => {
    return new Promise((resolve, reject) => {
      storageRef
        .child("images/" + photoId)
        .getDownloadURL()
        .then(url => resolve(url))
        .catch(error => reject(error));
    });
  };

  useEffect(() => {
    console.log("trigger");
    Promise.all(
      photos.map(async photoId => {
        const url = await getImage(photoId);
        return url;
      })
    )
      .then(photoUrls => {
        setPhotos(photoUrls);
      })
      .catch(e => console.log(e));
  }, [photos]);

return (...)
}

I have passed the photos prop into the dependency array of my useEffect hook, so it should fire when the photos prop changes. I can see that the prop is indeed changing in the console, but my useEffect hook does not fire when the prop change comes through. This is what appears in my console:

Why is the useEffect not firing twice? From my understanding it should fire when the component renders the first time, and fire again every time the photos prop changes.

I am using a useEffect hook to make an API call depending on data from a photos prop being passed in.

const ImageCarousel = ({ src, photos }) => {
  const [photoList, setPhotos] = useState([]);
  const storageRef = firebase.storage().ref();
  console.log("photos prop:", photos);

  const getImage = photoId => {
    return new Promise((resolve, reject) => {
      storageRef
        .child("images/" + photoId)
        .getDownloadURL()
        .then(url => resolve(url))
        .catch(error => reject(error));
    });
  };

  useEffect(() => {
    console.log("trigger");
    Promise.all(
      photos.map(async photoId => {
        const url = await getImage(photoId);
        return url;
      })
    )
      .then(photoUrls => {
        setPhotos(photoUrls);
      })
      .catch(e => console.log(e));
  }, [photos]);

return (...)
}

I have passed the photos prop into the dependency array of my useEffect hook, so it should fire when the photos prop changes. I can see that the prop is indeed changing in the console, but my useEffect hook does not fire when the prop change comes through. This is what appears in my console:

Why is the useEffect not firing twice? From my understanding it should fire when the component renders the first time, and fire again every time the photos prop changes.

Share Improve this question edited Feb 19, 2020 at 9:57 Mese 8771 gold badge13 silver badges26 bronze badges asked Feb 19, 2020 at 9:13 laythqlaythq 1371 gold badge1 silver badge5 bronze badges 3
  • Did you try to pass different photo prop value to the component and checked whether the useEffect is triggered ?. useEffect will trigger only when the new value is different from the Old Value. – Raj Kumar Commented Feb 19, 2020 at 10:19
  • Yes, have tried using a different prop instead of passing an empty array and it still does not trigger the useEffect. – laythq Commented Feb 19, 2020 at 14:29
  • as per the console screenshot, i felt your passing the same value to the props, thats why i informed like that, if you added your passing props, it will great to check exact issue – Raj Kumar Commented Feb 19, 2020 at 14:36
Add a comment  | 

3 Answers 3

Reset to default 18

Try to make sure your photos prop is immutable, meaning, you send a new array each time there is a change and not mutating the array

This may not be the most correct answer, but I've tried this and it works. Hat tip to https://dev.to/stephane/how-to-make-sure-useeffect-catches-array-changes-fm3

useEffect(() => {
  console.log("trigger");
  Promise.all(
    photos.map(async photoId => {
      const url = await getImage(photoId);
      return url;
    })
  )
  .then(photoUrls => {
    setPhotos(photoUrls);
  })
  .catch(e => console.log(e));
}, [JSON.stringify(photos])); // stringify the array used as the trigger, and it'll catch the change

useEffect will update if you pass the new data, find the sample code below and check the console.log.

    import React, { useState, useEffect } from "react";

    const EffectCheck = ({value}) => {
        console.log('Component Trigger', value);
        useEffect(() => {
            console.log('Updated Effect', value);
        },[value]);

        return (
            <div>{value}</div>
        )
    }

    export default function() {
        const [checkValue, setCheckValue] = useState(Math.random());
        const [dynamicCheckValue, setdyamicCheckValue] = useState(Math.random());

        return (
            <>
                <div><h3>No Update</h3>
                    <EffectCheck value={checkValue}/>
                </div>
                <div><h3>New Update</h3>
                    <EffectCheck value={dynamicCheckValue}/>
                </div>
                <button onClick={() => setCheckValue('Math.random()')}> No Update</button>
                <button onClick={() => setdyamicCheckValue(Math.random())}> New Update</button>
            </>
        );
    }


本文标签: javascriptReact useEffect hook does not fire when prop dependency changesStack Overflow