应用影响会话的身份验证更改并反应父组件

Apply auth changes that affect to session and react parent component

我将尽我所能在这里解释我的问题,但这将具有挑战性,所以请耐心等待。

我有一个使用 firebase 身份验证在 react + firebase 中开发的网络应用程序,登录目前仅由邮件和密码提供程序处理。我正在使用 React 路由器和 firebase 9。

当有人登录或注销时,身份验证令牌会保留在会话存储中,并且我在 App 组件(我页面的第一层)中有一个条件显示日志 in/register link 如果用户未登录,我的帐户 link 如果用户已登录。问题是我需要重新加载页面才能看到更改,登录时你会被重定向到另一条路线,但作为一个 React 应用程序,它不会重新加载整个页面。

我的App.js

  const auth = getAuth();
  const App = () => {
  const [user, setUser] = useState();
  const [expanded, setExpanded] = React.useState(true);
  const [activeKey, setActiveKey] = React.useState('1');

  const handleLogout = () => {
    signOut(auth).then(()=> {
      setUser({});
      sessionStorage.clear();
      console.log("unset user");
    }).catch((err) => {
      console.error(err);
      alert(err.message);
    })
  };

  onAuthStateChanged(auth, (user) => {
    if (user) {
      setUser(user)
      sessionStorage.setItem("user", JSON.stringify(user))
      const uid = user.uid;
      console.log("set user")

    } else {

    }
  });

    useEffect(() => {
      const loggedInUser = sessionStorage.getItem("user");
      if (loggedInUser != null) {
        const foundUser = loggedInUser.toString();
        setUser(foundUser);
        console.log(user)
      }
    }, []);
    return (
      <div>

              <li className="nav-item">
                {
                  (sessionStorage.user ?
                    <div className="d-flex justify-content-around row">
                      <Link className="nav-link" to="/user/perfil">Mi cuenta</Link>
                    </div>
                    : <Link className="nav-link" to="/login">Iniciar sesión / Registrarse</Link>
                  )
                }

          </li>
  </div>
)

}

导出默认应用;

我的login.js

const auth = getAuth();
console.log(auth.currentUser);
const loginWithEmailAndPassword = async (email, password) => {

setPersistence(auth, browserSessionPersistence)
    .then(() => {
        signInWithEmailAndPassword(auth, email, password)

    }).catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        alert(error.message)
    })
}

class Login extends Component {
constructor() {
    super();
    this.state = {
        email: "",
        password: "",
        redirect: "",
    };
}
handleChangeEmail = () => {
    this.setState({ email: document.getElementById("email").value });
    console.log(this.state);
}
handleChangePassword = () => {
    this.setState({ password: document.getElementById("password").value })
}
handleRedirect = () => {
    this.setState({ redirect: "/aplicacion" });
    console.log(this.state);
}
handleClick = async () => {
    try {
        await loginWithEmailAndPassword(
            this.state.email,
            this.state.password
        );
        this.handleRedirect();
    } catch (err) {
        console.error(err);
        alert(err.message);
    }
};
render() {

    if (this.state.redirect) {
        return <Navigate to={this.state.redirect} />
    }
    return (
        <div className="d-flex justify-content-center" >
                                    <div className="col-6">
                                        <Link to='/recuperacion' className="tiny-text">He olvidado mi contraseña</Link>
                                    </div>
        </div>
    )
}

}

编辑:我目前正在为将位于 App.js 中的应用程序的另一部分开发重定向检测功能,目前它只是一个数组,用于检查最后两条路线是否是与重定向情况相同,这对我来说太过暴力了,但这就是我现在所拥有的。

好的,我最终通过使用状态和挂钩解决了重定向问题让我解释一下:

我创建了一个名为 redirectState 的新状态及其 setter 和一个导航状态:

 const [redirectState, setRedirectState] = useState()
 let navigate = useNavigate()

然后我只需要在身份验证状态更改时设置它,以便应用程序知道何时重定向以及何时不重定向:

onAuthStateChanged(auth, (user) => {
if (user) {
  setUser(user)
  sessionStorage.setItem("user", JSON.stringify(user))
  const uid = user.uid;
  console.log("set user");
  console.log(uid)
  setRedirectState("redirect")
} else {
  sessionStorage.clear();
  setRedirectState()
}});

最后我使用了反应路由器 useNavigate 钩子来直接控制重定向:

  useEffect(() => {
const loggedInUser = sessionStorage.getItem("user");
console.log("checking user...")
if (loggedInUser != undefined) {
  const foundUser = loggedInUser.toString();
  setUser(foundUser);
  console.log(user);
  navigate("/aplicacion")
}else{
  console.log("no user")
  navigate("/")
}}, [redirectState]);

它可能看起来很粗糙,但功能目前有效,当调用导航功能时所有组件更新,这样应用程序每次都会显示正确的 link,有一些我放错地方的资源想修复,但这将在另一点进行,如果我找到改进其编码方式的方法,将保持此 post 更新。

但现在我认为它已经解决了! :-)