reactjs 为什么我的注销功能被拒绝?

mlmc2os5  于 2023-04-11  发布在  React
关注(0)|答案(1)|浏览(90)

我试图用redux工具包做一个注销功能,但是当函数被分派时,它被拒绝了,错误消息是cannot read property of undefined
这是我的组件:

import React from 'react'
import { Container, AppBar, Toolbar, styled, InputBase, Button } from '@mui/material'
import { useDispatch, useSelector } from 'react-redux'
import { logoutUser } from '../../reducers/auth/authSlice'

const Search = styled("div")(({theme}) => ({
    backgroundColor: "white",
    padding: "10px",
    borderRadius: "10px",
    width: "40%"
}))


export default function Navbar() {

  const dispatch = useDispatch();
  const isAuthenticated = useSelector(state => state.user.isAuthenticated);
  const handleLogout = () => {
    dispatch(logoutUser());
    console.log(isAuthenticated)
  };

  return (
    <AppBar position='static' color='primary'>
        <Container>
            <Toolbar>
                <Search>
                    <InputBase placeholder='Search...' fullWidth={true}/>
                </Search>
                    {isAuthenticated ? <Button
                    type='submit' 
                    variant="contained" 
                    color="primary"
                    onClick={handleLogout}
                    >
                    Logout
                    </Button> : ''}
                   
            </Toolbar>
        </Container>
    </AppBar>
  )
}

我想在我的导航栏中呈现注销按钮,只有当用户被验证时,当我点击注销按钮时,会触发handleLogout,它会调度logoutUser操作。问题是被拒绝了,我不知道为什么。
所以我假设它与我的切片以及我如何开发函数有关

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'

import setAuthToken from '../../utils/setAuthToken';

import axios from 'axios';

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

export const loadUser = createAsyncThunk(
  'user/loadUser',
  async ({ rejectWithValue }) => {

    if(localStorage.token){
      setAuthToken(localStorage.token);
    }

    try {
      const res = axios.get('http://localhost:3000/api/auth');
      return res.data;
    } catch (error) {
      return rejectWithValue(error.response.data);
    }
  }
)

export const registerUser = createAsyncThunk(
  'user/registerUser',
  async (newUser, { rejectWithValue }) => {
    try {
      const config = {
        headers: {
          'Content-Type': 'application/json',
        },
      };
      const body = JSON.stringify(newUser);
      const response = await axios.post(
        'http://localhost:3000/api/users',
        body,
        config
      );
      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:3000/api/auth', body, config);

    dispatch(loadUser());
    console.log(body)
    return res.data;
  } catch (err) {
    return rejectWithValue(err.response.data);
  }
});

export const logoutUser = createAsyncThunk(
  'auth/logout',
  async (_, { getState, rejectWithValue }) => {
    try {
      // Remove token from local storage
      localStorage.removeItem('token');

      // Reset authentication state
      const state = getState();
      state.user.isAuthenticated = false;
      state.user.token = null;
      state.user.user = null;

      return true;
    } catch (err) {
      return rejectWithValue(err.response.data);
    }
  }
);



export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    
  },
  extraReducers: {
    [registerUser.pending]: (state) => {
      state.loading = true;
      state.error = null;
    },
    [registerUser.fulfilled]: (state, action) => {
      state.user = action.payload;
      state.loading = false;
      state.error = null;
      
    },
    [registerUser.rejected]: (state, action) => {
      state.loading = false;
      state.error = action.payload;
    },
    [loadUser.pending]: (state) => {
      state.loading = true;
      state.error = null;
    },
    [loadUser.fulfilled]: (state, action) => {
      state.isAuthenticated = true;
      state.user = action.payload;
      state.loading = false;
      state.error = false;
    },
    [loadUser.rejected]: (state, action) => {
      state.loading = false;
      state.isAuthenticated = false;
      state.error = action.payload;

    },
    [loginUser.pending]: (state) => {
      state.loading = true;
      state.error = null;
    },
    [loginUser.fulfilled]: (state, action) => {
      state.token = localStorage.setItem('token', action.payload.token);
      state.isAuthenticated = true;
      state.loading = false;
      state.user = action.payload.user;
    },
    [loginUser.rejected]: (state, action) => {
      state.isAuthenticated = false;
      state.loading = false;
      state.error = action.payload;
    },
    [logoutUser.pending]: (state) => {
      state.loading = true;
      state.error = null;
    },
    [logoutUser.fulfilled]: (state) => {
      state.loading = false;
      state.isAuthenticated = false;
      state.token = null;
      state.user = null;
    },
    [logoutUser.rejected]: (state, action) => {
      state.loading = false;
      state.error = action.payload;
    }
  }
})

// Action creators are generated for each case reducer function
export const {  } = userSlice.actions

export default userSlice.reducer
c3frrgcw

c3frrgcw1#

handleLogout函数中,唯一可以访问data属性的地方是logoutUser函数中的以下行:

return rejectWithValue(err.response.data);

(next时间,我建议你提供一个最小复制示例和/或错误堆栈跟踪,以便其他人可以更快地找到它)。
这表明您的代码抛出了一些错误,这些错误被catch块捕获。但是,err.responseundefined,这意味着err不是Axios错误,尽管您的错误处理程序期望这样做。
更好的方式来写这一行:

return rejectWithValue(err.response?.data ?? err.message);

这可以确保您不会访问不存在的嵌套属性,并且始终有一个参数传递给rejectWithValue
然后,您可以检查实际错误并找出代码抛出错误的原因。

相关问题