反应无法在函数内部使用setState的useEffect

时间:2020-06-25 21:33:27

标签: reactjs react-native

我有一种情况,其中在button click上调用了一个异步函数,并且返回值设置了状态值。之后,将调用另一个需要先前设置值的函数。由于它在函数内部,因此我无法使用useEffect。如何实现呢?

const [user, setUser] = React.useState(null);

const handleSignIn = async () => {

    const result = await Google.logInAsync(config);
    const { type, idToken } = result;

    setUser(result?.user);

    if (type === "success") {

        AuthService.googleSignIn(idToken)
          .then((result) => {
              const displayName = `${user?.givenName} ${user?.familyName}`;

              signIn({
                 uid: user.uid,
                 displayName: displayName,
                 photoURL: user.photoUrl,
              });
          })
          .catch((error) => {
      });
  }
};

在此,单击按钮会调用handleSignIn,并根据从user获得的结果来设置Google.logInAsync的状态值。然后调用AuthService.googleSignIn,并在成功时使用user对象,但有时不可用。

1 个答案:

答案 0 :(得分:1)

cbr的评论打在了头上。您需要将setUser之后的所有内容包装在自己的useEffect中,这取决于user状态变量。像这样:

const [result, setResult] = React.useState(null);

const handleSignIn = async () => {

    const result = await Google.logInAsync(config);
    setUser(result);

};

useEffect( () => {

  if (result) {

    const { type, idToken, user } = result;

    if (type === "success") {

        AuthService.googleSignIn(idToken)
          .then((result) => {
              const displayName = `${user?.givenName} ${user?.familyName}`;

              signIn({
                 uid: user.uid,
                 displayName: displayName,
                 photoURL: user.photoUrl,
              });
          })
          .catch((error) => {
          });
    }

  }

}, [result])

这里发生的是您的handleSignIn设置了user变量。每当useEffect变量更新时,您的user就会运行。如果存在,它将使用新的AuthService值运行您的user代码。

或者,您可以完全直接使用useEffect来跳过result.user。从result中将其与typeidToken一起提取,然后直接使用。如果以后需要,仍可以使用setUser函数将其保存为状态:

const [user, setUser] = React.useState(null);

const handleSignIn = async () => {

    const result = await Google.logInAsync(config);
    const { type, idToken, user } = result;

    setUser(user);

    if (type === "success") {

        AuthService.googleSignIn(idToken)
          .then((result) => {
              const displayName = `${user?.givenName} ${user?.familyName}`;

              signIn({
                 uid: user.uid,
                 displayName: displayName,
                 photoURL: user.photoUrl,
              });
          })
          .catch((error) => {
      });
  }
};