首页 > 解决方案 > 带有自定义 Hook 的登录表单 React JS

问题描述

我目前正在学习 React JS。教程 我之前已经有一个 PHP 后端,我想创建一个登录表单,其中后端的结果是 JWT。为此,我在 React JS 中使用了一个自定义钩子。这是我创建的代码。

应用程序.js

import "./App.css";
import React from "react";
import { Routes } from "../config";
import { useToken } from "../hooks";
import Login from "./Login";

const App = () => {

  const { token, setToken } = useToken();

  if (!token) {
    return <Login setToken={setToken} />;
  }

  return <Routes />;
};
export default App;

使用令牌()

import { useState } from "react";

export default function useToken() {
  const getToken = () => {
    const tokenString = localStorage.getItem("token");
    const userToken = JSON.parse(tokenString);
    return userToken?.token;
  };

  const [token, setToken] = useState(getToken());

  const saveToken = (userToken) => {
    localStorage.setItem("token", JSON.stringify(userToken));
    setToken(userToken.token);
  };

  return {
    setToken: saveToken,
    token,
  };
}

登录/index.js

import React, { useState } from "react";
import PropTypes from "prop-types";
import { Button, Card, Col, Container, Form, Row } from "react-bootstrap";
import "./login.css";

async function loginUser(credentials) {
  const url = "v1/auth";
  const user = new FormData();
  user.append("username", credentials.username);
  user.append("password", credentials.password);

  return fetch(url, {
    method: "POST",
    body: user,
  }).then((data) => data.json());
}

export default function Login({ setToken }) {
  const [username, setUserName] = useState();
  const [password, setPassword] = useState();

  // Handle submit
  const handleSubmit = async (e) => {
    e.preventDefault();
    const token = await loginUser({ username, password });
    setToken(token);
  };

  return (
    <div id="login-page">
      <Container>
        <Row className="d-flex justify-content-md-center align-items-center vh-100">
          <Col sm={12} md={6}>
            <Card>
              <Form onSubmit={handleSubmit}>
                <Card.Header>Sign In</Card.Header>
                <Card.Body>
                  <Form.Group controlId="loginform-username">
                    <Form.Label>Username</Form.Label>
                    <Form.Control
                      type="text"
                      placeholder="Username"
                      name="username"
                      onChange={(e) => setUserName(e.target.value)}
                    />
                  </Form.Group>

                  <Form.Group controlId="loginform-password">
                    <Form.Label>Password</Form.Label>
                    <Form.Control
                      name="password"
                      type="password"
                      placeholder="Password"
                      onChange={(e) => setPassword(e.target.value)}
                    />
                  </Form.Group>
                </Card.Body>
                <Card.Footer>
                  <Button
                    variant="primary"
                    type="submit"
                    className="float-right"
                  >
                    Login
                  </Button>
                  <div className="clearfix"></div>
                </Card.Footer>
              </Form>
            </Card>
          </Col>
        </Row>
      </Container>
    </div>
  );
}

Login.propTypes = {
  setToken: PropTypes.func.isRequired,
};

成功登录后,我将令牌保存到本地存储。但我收到以下警告。

index.js:1 Warning: Failed prop type: The prop `setToken` is marked as required in `Login`, but its value is `undefined`.

如何解决这个问题?非常感谢任何帮助

更新

路线

import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Login, Home } from "../../pages";

const Routes = () => {
  return (
    <Router>
      <Switch>
        <Route path="/login">
          <Login />
        </Route>

        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
};

export default Routes;

标签: javascriptreactjs

解决方案


Routes你打电话Login但从不通过它setToken,这是必需的。一种选择是将setToken函数向下传递Routes

应用程序.js

import "./App.css";
import React from "react";
import { Routes } from "../config";
import { useToken } from "../hooks";
import Login from "./Login";

const App = () => {

  const { token, setToken } = useToken();

  if (!token) {
    return <Login setToken={setToken} />;
  }

  return <Routes setToken={setToken} />;
};
export default App;

路由.js

import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Login, Home } from "../../pages";

const Routes = ({ setToken }) => {
  return (
    <Router>
      <Switch>
        <Route path="/login">
          <Login setToken={setToken} />
        </Route>

        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
};

export default Routes;

推荐阅读