javascript - React Context 和 hookrouter 不会在组件挂载时重定向

标签 javascript reactjs routes hookrouter

我正在尝试使用 CodeSandbox ( here )“复制”我的真实世界项目。我有一个登录表单,登录时,它会设置一个带有身份验证数据的 cookie。当 <LoginPage>组件安装,它应该检查该 cookie 并重定向回 <HomePage>组件(如果存在)。

在我的例子中,它没有按预期工作,因为它一直等到我在 <LoginPage> 中写了一些东西。形式。

根据hookrouter documentation navigate()应该作为 react-router-dom <Redirect /> 工作组件。

所以,这是项目 src文件夹结构:

  • 来源
    • index.js
    • 组件
      • 页面
        • 首页
          • index.js
        • 登录
          • index.js
    • 上下文
      • 授权
        • auth.js
        • index.js

代码:

App : 源代码/index.js

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { useRoutes, A, navigate } from "hookrouter";
import { useCookies } from "react-cookie";

import HomePage from "./components/pages/Home";
import LoginPage from "./components/pages/Login";

import AuthContextWrapper from "./context/Auth";

const Logout = () => {
  const [cookies, setCookie, removeCookie] = useCookies(["token"]);
  useEffect(() => {
    console.log("Logout triggered");
    removeCookie("token");
    navigate("/", true);
  }, []);
  return <p>Closing session</p>;
};

const routes = {
  "/": () => <HomePage />,
  "/login": () => <LoginPage />,
  "/logout": () => <Logout />
};

const App = () => {
  const Router = useRoutes(routes);
  return Router ? (
    <AuthContextWrapper>{Router}</AuthContextWrapper>
  ) : (
    <h1>
      Error 404: <A href="/">Go back</A>
    </h1>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

<HomePage /> : src/components/pages/Home/index.js

import React, { Fragment, useContext } from "react";
import { A } from "hookrouter";
import AuthContext from "../../../context/Auth/auth";

const HomePage = () => {
  const context = useContext(AuthContext);
  console.log("Home context", context);
  return (
    <Fragment>
      <A href="/login">Login page</A>
      {context.token.length ? <A href="/logout">Logout</A> : ""}
    </Fragment>
  );
};

export default HomePage;

<LoginPage /> : src/components/pages/Login/index.js

import React, { useState, useContext, useEffect } from "react";
import AuthContext from "../../../context/Auth/auth";
import { navigate } from "hookrouter";

const LoginPage = () => {
  const context = useContext(AuthContext);
  const [emailState, setEmailState] = useState("");
  const [passwordState, setPasswordState] = useState("");
  const [statusState, setStatusState] = useState({
    color: "black",
    status: ""
  });

  useEffect(() => {
    console.log("Login context:", context);
    if (context.token) {
      navigate("/");
    }
  }, []);

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={emailState}
        onChange={e => setEmailState(e.target.value)}
        placeholder="Email"
      />
      <input
        value={passwordState}
        onChange={e => setPasswordState(e.target.value)}
        placeholder="Password"
        type="password"
      />
      <p style={{ color: statusState.color }}>{statusState.status}</p>
      <button>Login</button>
    </form>
  );

  async function handleSubmit(e) {
    e.preventDefault();
    setStatusState({
      color: "blue",
      status: "Validating"
    });
    await context.login(emailState, passwordState);
    if (context.error) {
      setStatusState({
        color: "red",
        status: context.error
      });
    }
    if (context.token) {
      navigate("/");
    }
  }
};

export default LoginPage;

<AuthContextWrapper /> : src/context/Auth/index.js

import React, { useEffect } from "react";
import Context from "./auth";
import { useCookies } from "react-cookie";

const AuthContextWrapper = props => {
  const [cookies, setCookie] = useCookies(["token"]);
  const defaultValue = {
    token: "",
    error: "",
    loading: false,
    login: async (email, password) => {
      setTimeout(() => {
        defaultValue.loading = true;
        if (password !== "123") {
          defaultValue.error = "Wrong credentials";
        } else {
          defaultValue.error = "";
          defaultValue.token = "jwtencodedtoken$123";
          setCookie("token", defaultValue.token);
        }
      }, 1000);
      defaultValue.loading = false;
    }
  };
  useEffect(() => {
    if (cookies.token) {
      defaultValue.token = cookies.token;
    }
  });
  return (
    <Context.Provider value={defaultValue}>{props.children}</Context.Provider>
  );
};

export default AuthContextWrapper;

所以,我想我的脑袋刚刚爆炸了... This is a live example生活在 CodeSandbox 中。钩子(Hook)可能有问题(我还在学习它们)。

为什么这不起作用?我究竟做错了什么?任何意见表示赞赏。

最佳答案

好的,我更新了您的代码沙箱 here .

src/context/Auth/index.js 的更改

您的上下文提供者有点笨拙。如果您尝试像使用登录功能那样直接操作一个对象,您将度过一段糟糕的时光。如果您想查看更新,请将它们绑定(bind)到状态并将它们作为值传递给您的提供者。

src/components/pages/Login/index.js 的更改

handleSubmit 函数不必是异步的,而且如果不让登录函数成为一个 promise ,您如何设置它也可能会有问题。您最终会提前返回 await 而不是在超时之后返回。

您最好使用适当的 dependenciesuseEffect Hook 中的上下文更新使用react.这样,无论何时上下文更新,您都可以在此组件中进行必要的更新。

关于javascript - React Context 和 hookrouter 不会在组件挂载时重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58033342/

相关文章:

javascript - Webpack + React : pass commit SHA from webpack to JS

asp.net-mvc - 为什么在 ASP.NET MVC 3 中,默认路由不适用于名为 "ContentController"的 Controller ?

Angular - 我需要避免破坏组件

javascript - 如何让 TinyMce 用内联样式替换已弃用的标签?

javascript - 在具有动态值的函数上使用的变量不允许我通过 ajax 发送表单

javascript - RxJS - Fire 按顺序订阅

reactjs - 在 SPA (React JS) 中向 Azure AD 组授权用户的最佳方法

javascript - jQuery 使用 td 值作为 img 的 src

node.js - Node.js 和 React 之间的 Websocket 握手错误

ruby-on-rails - Rails 路由可在单个应用程序上处理多个域