redux 为什么我的诉讼在第一次被驳回,但后来又被提起?

yjghlzjz  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(129)

我有问题,我的登录功能在我的前端。我确信这是在我的前端造成的,因为在 Postman 中,我所有的数据流都工作正常。
我有一个登录组件,它从表单中捕获电子邮件和密码,并使用数据调度一个操作:

import React, { useState }  from 'react'
import { useDispatch, useSelector } from 'react-redux';
import { loginUser } from '../../slices/authSlice';
import '../../styles/components/Auth/LoginForm.css';
import { BrowserRouter , Navigate } from 'react-router-dom';

const LoginForm = () => {
  
  const dispatch = useDispatch();

  const [formData, setFormData] = useState({
    email: "",
    password: ""
  });

  const {email, password } = formData;

  const onChange = (e) =>
    setFormData({ ...formData, [e.target.name]: e.target.value });

  const onSubmit = (e) => {
    e.preventDefault();
      dispatch(loginUser({email, password}));
  };

  return (
    <form action="" className="login__form" onSubmit={(e) => onSubmit(e)}>
      
      <div className="field-container">
        <label>Email</label>
        <input
          type="email"
          name="email"
          value={email}
          onChange={(e) => onChange(e)}
        />
      </div>
      
      <div className="field-container">
        <label>Password</label>
        <input
          type="password"
          name="password"
          id=""
          value={password}
          onChange={(e) => onChange(e)}
        />
      </div>
      
      <button type="submit">Log In</button>
    </form>
  );
};

export default LoginForm;

后来我有我的authSlice与不同的方法:

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from 'axios';
import setAuthToken from "../utils/setAuthToken";

const initialState = {
    token: localStorage.getItem('token'),
    isAuthenticated: false,
    isLoading: true,
    user: null
}

export const loadUser = createAsyncThunk(
    'auth/loadUser',
    async (_,{ rejectWithValue }) => {
  
      if(localStorage.token){
        setAuthToken(localStorage.token);
      }
  
      try {
        const res = await axios.get('http://localhost:5000/api/auth/me');
        return res.data;
      } catch (error) {
        return rejectWithValue(error.response.data);
      }
    }
  )
  
  export const registerUser = createAsyncThunk(
    'auth/registerUser',
    async (newUser, { dispatch, rejectWithValue }) => {
      try {
        const config = {
          headers: {
            'Content-Type': 'application/json',
          },
        };
        const body = JSON.stringify(newUser);
        const response = await axios.post(
          'http://localhost:5000/api/auth/register',
          body,
          config
        );
        dispatch(loadUser(newUser));
        return response.data;
      } catch (error) {
        return rejectWithValue(error.response.data);
      }
    }
  );
  
  
  export const loginUser = createAsyncThunk('auth/login', async ({ email, password }, { dispatch, rejectWithValue }) => {
    const body = { email, password };
  
    const config = {
      headers: {
        'Content-Type': 'application/json',
      },
    };
  
    try {
      const res = await axios.post('http://localhost:5000/api/auth/login', body, config);
  
      dispatch(loadUser(res.data));
      console.log(body)
      return res.data;
    } catch (err) {
      return rejectWithValue(err.response.data);
    }
  });



export const authSlice = createSlice({
    name: 'auth',
    initialState,
    reducers:{
        logout:(state, action) => {
            state.token = null;
            localStorage.removeItem('token');
            state.isAuthenticated = false;
            state.user = null;
        }
    },
    extraReducers: (builder) => {
        builder
            .addCase(loadUser.pending, (state) => {
                state.isLoading =true;
            })
            .addCase(loadUser.fulfilled, (state, action) => {
                state.isLoading = false;
                state.isAuthenticated = true;
                state.user = action.payload;
            })
            .addCase(loadUser.rejected, (state, action) => {
                state.isLoading = false;
                state.isAuthenticated = false;
                console.log(action.payload);
            })
            .addCase(registerUser.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(registerUser.fulfilled, (state, action) => {
                state.token = localStorage.setItem('token', action.payload.token);
                state.isLoading = false;
                state.isAuthenticated = true;
                state.user = action.payload;
            })
            .addCase(registerUser.rejected, (state, action) => {
                state.isLoading = false;
                /* state.isAuthenticated = false; */
                console.log(action.payload);
            })
            .addCase(loginUser.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(loginUser.fulfilled, (state, action) => {
                state.isAuthenticated = true;
                state.isLoading = false;
                state.user = action.payload;
                state.token = localStorage.setItem('token', action.payload.token);
            })
            .addCase(loginUser.rejected, (state, action) => {
                state.isAuthenticated = false;
                state.isLoading = false;
                state.user = null;
                console.log(action.error);
                
              }
            )
    }
});

export const { logout } = authSlice.actions;

export default authSlice.reducer;

这是我的util函数setAuthToken.js:

import axios from 'axios';

const setAuthToken = (token) => {
  if (token) {
    axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
  } else {
    delete axios.defaults.headers.common['Authorization'];
  }
  console.log(axios.defaults.headers.common['Authorization']);
};

export default setAuthToken;

问题如下。当我在我的redux devtools中提交表单时,我得到了正确的数据auth/login/fullfilled。但auth/loaduser被拒绝,并获取以下数据:

type(pin):"auth/loadUser/rejected"
success(pin):false
error(pin):"Not authorized to access this route"
success(pin):true
token(pin):"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkNzEzOTk1YjcyMWMzYmIzOGMxZjVkNSIsImlhdCI6MTY4NjA4NDA0MiwiZXhwIjoxNjg2MDg1MDQyfQ.QorBCHQW5QBXdQHG0HD3fXLWsWX3aOVQyD8uKmEZMoI"
requestId(pin):"NLUh3rFIYsFilYjBGkbmK"
rejectedWithValue(pin):true
requestStatus(pin):"rejected"
aborted(pin):false
condition(pin):false
message(pin):"Rejected"

我不知道为什么我被拒绝,如果令牌是有效的。
所以我的登录有bug。
在第一次登录中,我得到了auth/login/fullfillled和auth/loaduser/rejected,但令牌在我的本地存储中设置正确。
现在,如果我尝试再次登录,令牌已经设置,我得到两个操作都已完成。
为什么我在第一次得到auth/login/fulfilled和auth/loaduser/rejected?

xzlaal3s

xzlaal3s1#

loginUser操作不会设置任何令牌值、状态或localStorage中的任何内容。***将token值设置为state/localStorage的是loginUser.fulfilled操作,特别是在处理它的reducer函数中。这是对Redux reducer函数的一种相当无效的使用,尽管reducer函数应该是纯粹的,没有副作用,无论是有意还是无意的。这意味着虽然loginUser仍在处理并分派loadUser(res.data),但Redux状态尚未更新。这意味着localStorage也没有更新。
这里我的建议是将localStorage更新移动到Thunk中,在那里异步和副作用逻辑更合适。

export const loginUser = createAsyncThunk(
  'auth/login',
  async ({ email, password }, { dispatch, rejectWithValue }) => {
    const body = { email, password };
  
    const config = {
      headers: {
        'Content-Type': 'application/json',
      },
    };
  
    try {
      const { data } = await axios.post(
        'http://localhost:5000/api/auth/login',
        body,
        config
      );

      localStorage.setItem('token', data.token);
  
      dispatch(loadUser(data));
      return data;
    } catch (err) {
      return rejectWithValue(err.response.data);
    }
  }
);
export const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    ...
  },
  extraReducers: (builder) => {
    builder
      ...
      .addCase(loginUser.fulfilled, (state, action) => {
        state.isAuthenticated = true;
        state.isLoading = false;
        state.user = action.payload;
        state.token = action.payload.token;
      })
      ...
  }
});

相关问题