只有 运行 次 useEffect 提取在第一次 useEffect 提取被触发并在上下文中设置用户之后

Only run a useEffect fetch after first useEffect fetch has fired and setUser in context

我需要调用保管箱 api 两次。第一个 useEffect 获取名称和路径,然后将它们推送到上下文中的空白数组中。然后我需要触发第二个 useEffect,它依赖于从第一个 useEffect 填充的数组。我尝试使用 useState 并创建 loading 和 setLoading,然后将 useEffect 的内部包装在 if(loading) 中,但这没有用,因为我猜它只会在安装组件时尝试触发。如何在第一个 useEffect 完成后制作第二个 useEffect 运行?

const [user, setUser] = useContext(UserContext);

首次使用效果:

useEffect(() => {
    var myHeaders = new Headers();
    myHeaders.append(
      'Authorization',
      'Bearer XXXXXXXXXXXXXXX',
    );
    myHeaders.append('Content-Type', 'application/json');

    var raw = JSON.stringify({path: `/${user.username}`});

    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow',
    };

    fetch('https://api.dropboxapi.com/2/files/list_folder', requestOptions)
      .then(response => response.json())
      .then(data => {
        let tmpArray = [];
        let tmpArrayTwo = [];
        for (var i = 0; i < data.entries.length; i++) {
          tmpArray.push(data.entries[i].name);
          tmpArrayTwo.push(data.entries[i].path_lower);
        }
        setUser({
          ...user,
          imageNames: tmpArray,
          imagePaths: tmpArrayTwo,
        });
      })
      .catch(error => console.log('error', error));
  }, []);

第二次使用效果:

useEffect(() => {
    let tmpArray = [];
    var myHeaders = new Headers();
    myHeaders.append(
      'Authorization',
      'Bearer XXXXXXXXXXXXXX',
    );
    myHeaders.append('Content-Type', 'application/json');

    for (var i = 0; i < user.imagePaths.length; i++) {
      var raw = JSON.stringify({path: `/${user.imagePaths[i]}`});
      var requestOptions = {
        method: 'POST',
        headers: myHeaders,
        body: raw,
        redirect: 'follow',
      };
      fetch(
        'https://api.dropboxapi.com/2/files/get_temporary_link',
        requestOptions,
      )
        .then(response => response.json())
        .then(data => {
          tmpArray.push(data.link);
        })
        .catch(error => console.log('error', error));
    }
    console.log(tmpArray);
    setUser({
      ...user,
      imageLinks: tmpArray,
    });
  }, []);

我认为它与依赖项数组有关,但我放入其中的所有内容(如用户、setUser)都给了我一个无限循环,console.log 用于 user.imagePaths记录为 []。我知道 user.imagePaths 是在第一个 useEffect 之后填充的,但是第二个 useEffect 对于循环的 user.imagePaths.length 一直未定义。

您应该将user.imagePaths添加到第二个useEffect的依赖列表中。

我建议使用 async/await 并在单个 useEffect 中进行调用。

如果默认情况下未定义 user,那么您可能需要添加可选链接。

[更新]

尝试将第二个 useEffect 更改为:

useEffect(() => {
    var myHeaders = new Headers();
    myHeaders.append(
        'Authorization',
        'Bearer XXXXXXXXXXXXXX',
    );
    myHeaders.append('Content-Type', 'application/json');

    if (!user?.imagePaths) {
        return;
    }

    Promise.all(user.imagePaths.map(path => {
        var raw = JSON.stringify({path: `${path}`});
        var requestOptions = {
          method: 'POST',
          headers: myHeaders,
          body: raw,
          redirect: 'follow',
        };
        return fetch(
          'https://api.dropboxapi.com/2/files/get_temporary_link',
          requestOptions,
        )
          .then(response => response.json())
          .then(data => data.link)
          .catch(error => console.log('error', error));
      }),
    ).then(imageLinks => {
      setUser({
        ...user,
        imageLinks,
      });
    });
  }, [user?.imagePaths]);

据我了解。我建议您首先使用一个状态,以便在 React 的生命周期中拥有您的数据。

const [listFolders, setListFolders] = React.useState([])
const [user, setUser] = React.useState({})

您的第一个 useEffect 将加载到组件的第一个挂载上,并且不会在函数末尾的 [] 位置之后得到回调。这允许告诉 React 仅在无依赖时触发效果。

useEffect(() => {
   ...
}, [])

您的第二个 useEffect 将仅在数组 listFolders 更改时加载。 除此之外,这里的目标是连接您所有的承诺,以便它只更新一次用户。否则我们会遇到异步的麻烦。

useEffect(() => {
   if(listFolders.length){

      Promise.all([*put all your promise here*]).then((data) => {
          * concatenate your array of link
          setUser({
             ...user,
             imageLinks: arrayOfLinks,
          })
      })
    }
}, [listFolders])