prop依赖项更改时,react useEffect挂钩不会触发

时间:2020-02-19 09:13:25

标签: javascript reactjs react-hooks

我正在使用useEffect挂钩根据传入的photos道具中的数据进行API调用。

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 (...)
}

我已将photos prop传递到useEffect钩子的依赖项数组中,因此当photo prop更改时,它将触发。我可以看到道具确实在控制台中发生了变化,但是当道具发生变化时,我的useEffect钩子不会触发。这就是我的控制台中显示的内容:

Console logs

为什么useEffect不触发两次?据我了解,它应该在组件首次渲染时触发,并在photos道具每次更改时再次触发。

3 个答案:

答案 0 :(得分:5)

请尝试确保您的photos道具是不可变的, 意思是,每次发生更改时您都发送一个新数组,而不会更改该数组

答案 1 :(得分:2)

这可能不是最正确的答案,但我已经尝试过了,并且有效。 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

答案 2 :(得分:0)

useEffect将在您传递新数据,在下面找到示例代码并检查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>
            </>
        );
    }