微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

未找到 redux 存储并且无法为 React 中的特定路径呈现组件

如何解决未找到 redux 存储并且无法为 React 中的特定路径呈现组件

我正在 MERN 应用中实现密码重置功能。当用户输入他们想要重置密码的电子邮件地址时,他们会在他们的邮件中收到一个重置密码链接。现在,当他们访问该链接时,他们应该会看到在屏幕上呈现的 PasswordResetFormSecond 组件。 (无论令牌是否有效)。

但是,当我访问路径“/account/reset/:token”时,我没有看到 PasswordResetFormSecond 在屏幕上呈现。但是,我得到了正确的服务器响应。此外,未找到 redux 存储。

enter image description here

我做错了什么?

代码片段如下:

client/src/components/PasswordResetFormsecond.js

import React,{ useState } from "react";
import { useSelector,usedispatch } from "react-redux";
import { useFormik } from "formik";
import * as Yup from "yup";
import {
  fetchPasswordResetMount,fetchPasswordResetSubmit,} from "./stateSlices/passwordResetPasswordSlice";

const PasswordResetFormSecond = ({ history,match }) => {
  const { successMount,errorMount,successSubmit,errorSubmit } = useSelector(
    (state) => state.passwordResetPasswordStage
  );

  const dispatch = usedispatch();

  useState(() => {
    dispatch(fetchPasswordResetMount(match.params.token));
  },[]);

  const formik = useFormik({
    initialValues: {
      password: "",confirmPassword: "",},validationSchema: Yup.object({
      password: Yup.string().required("Please enter your password"),confirmPassword: Yup.string().required("Please enter your password"),}),onSubmit: async (values,{ resetForm }) => {
      const { password,confirmPassword } = values;
      dispatch(
        fetchPasswordResetSubmit({
          password,confirmPassword,token: match.params.token,})
      );
      if (successSubmit) {
        history.push("/registerLogin");
      }
    },});

  let condition = successMount || errorMount;

  return (
    <div className="col-10 col-sm-8 col-md-5 mx-auto">
      {condition && (
        <div className="login-form-wrapper">
          <div className="col-10 col-sm-8 col-md-5 mx-auto">
            <h1 className="font-weight-bold">Reset Password</h1>
          </div>
          <form onSubmit={formik.handleSubmit}>
            <div className="form-group col-10 col-sm-8 col-md-5 mx-auto mt-5">
              {errorSubmit && (
                <div className="alert alert-danger" role="alert">
                  {errorSubmit}
                </div>
              )}
            </div>
            <div className="form-group col-10 col-sm-8 col-md-5 mx-auto">
              <label htmlFor="password">Password</label>
              <input
                className="form-control form-control-lg"
                id="password"
                name="password"
                type="password"
                onChange={formik.handleChange}
                onBlur={formik.handleBlur}
                value={formik.values.password}
              />
              {formik.touched.password && formik.errors.password ? (
                <small className="form-text text-danger">
                  {formik.errors.password}
                </small>
              ) : null}
            </div>
            <div className="form-group col-10 col-sm-8 col-md-5 mx-auto">
              <label htmlFor="confirmPassword">Confirm Password</label>
              <input
                className="form-control form-control-lg"
                id="confirmPassword"
                name="confirmPassword"
                type="password"
                onChange={formik.handleChange}
                onBlur={formik.handleBlur}
                value={formik.values.password}
              />
              {formik.touched.confirmPassword &&
              formik.errors.confirmPassword ? (
                <small className="form-text text-danger">
                  {formik.errors.confirmPassword}
                </small>
              ) : null}
            </div>

            <div className="col-10 col-sm-8 col-md-5 mx-auto">
              <button
                type="submit"
                className="btn btn-lg btn-primary btn-block login-button"
              >
                Reset Password
              </button>
            </div>
          </form>
        </div>
      )}
    </div>
  );
};

export default PasswordResetFormSecond;

client/src/App.js

import React,{ useState } from "react";
import Header from "./components/Header";
import Home from "./components/Home";
import About from "./components/About";
import CV from "./components/CV";
import Projects from "./components/Projects";
import RegisterForm from "./components/RegisterForm";
import LoginForm from "./components/LoginForm";
import PasswordResetFormFirst from "./components/PasswordResetFormFirst";
import PasswordResetFormSecond from "./components/PasswordResetFormSecond";
import { Route,Switch } from "react-router-dom";

const App = () => {
  const [menuOpen,setMenuOpen] = useState(false);
  const handleMenuClick = () => {
    setMenuOpen(!menuOpen);
  };

  const handleOverlayClick = () => {
    setMenuOpen(!menuOpen);
  };

  const handleSidedrawerNavbarLinkClick = () => {
    setMenuOpen(!menuOpen);
  };
  return (
    <>
      <Header
        menuOpen={menuOpen}
        onMenuClick={handleMenuClick}
        onSidedrawerNavbarLinkClick={handleSidedrawerNavbarLinkClick}
        onOverlayClick={handleOverlayClick}
      />
      <Switch>
        <Route
          path="/account/reset/:token"
          component={PasswordResetFormSecond}
        />
        <Route path="/account/forgot" component={PasswordResetFormFirst} />
        <Route path="/about" component={About} />
        <Route path="/cv" component={CV} />
        <Route path="/projects" component={Projects} />
        <Route path="/registerLogin" component={LoginForm} />
        <Route path="/register" component={RegisterForm} />
        <Route path="/" exact component={Home} />
      </Switch>
    </>
  );
};

export default App;

client/src/staeSlices/passwordResetPasswordSlice.js

import { createSlice,createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

const initialState = {
  user: null,successMount: null,successSubmit: null,errorMount: null,updatedUser: null,errorSubmit: null,};

export const fetchPasswordResetMount = createAsyncThunk(
  "passwordReset/fetchPasswordResetMount",async (token,{ rejectWithValue }) => {
    try {
      const { data } = await axios.get(`/account/reset/${token}`);
      return data;
    } catch (err) {
      return rejectWithValue(err.response.data);
    }
  }
);
export const fetchPasswordResetSubmit = createAsyncThunk(
  "passwordResetPassword/fetchPasswordResetInfo",async ({ password,token },{ rejectWithValue }) => {
    try {
      const { data } = await axios.post(`/account/reset/${token}`,{
        password,});
      return data;
    } catch (err) {
      return rejectWithValue(err.response.data);
    }
  }
);

export const passwordResetSlice = createSlice({
  name: "passwordReset",initialState,reducers: {},extraReducers: {
    [fetchPasswordResetMount.fulfilled]: (state,action) => {
      state.user = action.payload;
      state.successMount = true;
    },[fetchPasswordResetMount.rejected]: (state,action) => {
      state.errorMount = action.payload.message;
    },[fetchPasswordResetSubmit.fulfilled]: (state,action) => {
      state.updatedUser = action.payload;
      state.successSubmit = true;
    },[fetchPasswordResetSubmit.rejected]: (state,action) => {
      state.errorSubmit = action.payload.message;
    },});

export default passwordResetSlice.reducer;

server/routes/passwordResetRoutes.js

const express = require("express");
const crypto = require("crypto");
const asyncHandler = require("express-async-handler");
const User = require("../models/usermodel");

const router = express.Router();

router.get(
  "/reset/:token",asyncHandler(async (req,res,next) => {
    const user = await User.findOne({
      passwordResetToken: req.params.token,passwordResetExpires: { $gt: Date.Now() },});

    if (user) {
      res.json(user);
    } else {
      const err = new Error("Password reset token is invalid or has expired");
      err.status = 404;
      next(err);
    }
  })
);
router.post(
  "/reset/:token",next) => {
    if (req.body.password === req.body.confirmPassword) {
      next();
    } else {
      const err = new Error("Passwords don't match.");
      err.status = 404;
      next(err);
    }
    const user = await User.findOne({
      passwordResetToken: req.params.token,});

    if (user) {
      user.password = req.body.password;
      user.passwordResetToken = undefined;
      user.passwordResetExpires = undefined;
      const updatedUser = await user.save();
      res.json(updatedUser);
    } else {
      const err = new Error("Password reset token is invalid or has expired");
      err.status = 404;
      next(err);
    }
  })
);
router.post(
  "/forgot",next) => {
    const user = await User.findOne({ email: req.body.email });

    if (user) {
      user.passwordResetToken = crypto.randomBytes(20).toString("hex");
      user.passwordResetExpires = Date.Now() + 3600000;
      await user.save();

      res.json({
        message: "You have been emailed a password reset link",});
    } else {
      const err = new Error("No account with that email exists");
      err.status = 404;
      next(err);
    }
  })
);

module.exports = router;

store.js

import { configureStore } from "@reduxjs/toolkit";
import loginReducer from "./components/stateSlices/loginSlice";
import registerReducer from "./components/stateSlices/registerSlice";
import passwordResetEmailReducer from "./components/stateSlices/passwordResetEmailSlice";
import passwordResetPasswordReducer from "./components/stateSlices/passwordResetPasswordSlice";

const loggedInUserFromStorage = localStorage.getItem("loggedInUser")
  ? JSON.parse(localStorage.getItem("loggedInUser"))
  : null;

const preloadedState = {
  login: {
    user: loggedInUserFromStorage,};

export default configureStore({
  reducer: {
    login: loginReducer,register: registerReducer,passwordResetEmail: passwordResetEmailReducer,passwordResetPassword: passwordResetPasswordReducer,preloadedState,});

GITHUB 仓库:https://github.com/sundaray/password-reset

解决方法

检查您的 GitHub 代码后,我发现您将请求代理到 /account/reset/:token,这与 localhost:5000 的前端路由相同。一个简单的解决方法是将前端路由重命名为其他名称。例如/password/reset/:token

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。