仅在第一次 useEffect fetch 已触发并在上下文中 setUser 后运行 useEffect fetch

时间:2021-03-21 19:09:11

标签: reactjs react-native react-hooks dropbox-api use-effect

我需要调用 dropbox api 两次。第一个 useEffect 获取名称和路径,然后将它们推送到上下文中的空白数组中。然后我需要第二个 useEffect 来触发,它依赖于从第一个 useEffect 填充的数组。我试图使用状态并创建加载和设置加载,然后将 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,
    });
  }, []);

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

2 个答案:

答案 0 :(得分:1)

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

我建议使用 async/await 并在 single 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]);

答案 1 :(得分:1)

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

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

由于函数末尾的 [] 位置,您的第一个 useEffect 将在组件的第一次安装时加载,并且不会在之后被回调。这允许告诉 React 仅在不依赖的情况下触发效果。

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

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

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

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