在新版中不再推荐直接导入redux,而是使用@reduxjs/toolkit
/src/store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import user from './reducer/user'
// 使用configureStore创建redux
export default configureStore({
reducer:{
user, // 模块化管理redux数据
}
})
在mian.tsx中导入使用
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { BrowserRouter} from "react-router-dom";
import { Provider } from "react-redux";
import store from "/src/store";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
)
// 如果需要在组件外部使用store,比如我需要在封装的utils工具request.ts中使用,可在此导出
export {store}
/src/utils/request.ts 外部js使用store
//对于axios进行二次封装
import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
import {store} from '@/main';
import { outLogin } from '@/store/reducer/user';
//创建axios实例
const requests:AxiosInstance = axios.create({});
//请求拦截器
requests.interceptors.request.use((config)=>{
// 通过getState拿到main.ts导出的store
const {user} = store.getState()
const token= user.token
const token_type= user.token_type
if (token) {
config.headers!['Authorization'] = token_type +token
}
return config;
})
//响应拦截器
requests.interceptors.response.use((res:any)=>{
const code:number = res.data.code
if (code !==200 && code !==2000 && code !==20000) {
if (code == 401) {
ElMessage.error('登录失效')
// 清除store 用户数据
store.dispatch(outLogin());
window.location.href = "/login";
}
// ElMessage.error(res.data.msg|| '请求错误')
}
return res.data;
},(error:any)=>{
// 响应失败的回调函数
return Promise.reject(new Error(error));
});
export default requests
/src/store/reducer 作为redux模块化管理文件夹,在下新建 user.ts 管理登录信息的数据
import api from "@/api";
import { createSlice,createAsyncThunk } from "@reduxjs/toolkit";
export interface User{
one:number
two:number
token:string
token_type:string
userInfo:Record<string,any>
}
// 定义数据
const initialState:User = {
one:6,
two:2,
token: localStorage.getItem('token')||'',
token_type: localStorage.getItem('token_type')||'',
userInfo:{}
};
// 异步方法需要使用createAsyncThunk创建
// params 为dispatch时传入的参数;store为initialState数据
const userInfo =createAsyncThunk( 'userInfo',async(params,store)=>{
const res =await api.login.getUserInfo()
// 异步函数必须要有返回值,返回操作结果
if (res.code==200) {
return res.data
}else{
return {}
}
})
// 创建redux
const userSlice = createSlice({
name:'user',
initialState,// 注意‘initialState’为固定名称,不要自定义此key值
reducers:{
// 同步方法,payload为dispatch时自定义传入的参数
addUser(state:User,{payload}){
console.log('接收到的参数:',payload);
state.one +=1
},
// 也可将网络请求放在组件方法中,得到结果再使用dispatch存入
getToken(state:User,{payload}){
state.token = payload.token
state.token_type = payload.token_type
localStorage.setItem('token',state.token)
localStorage.setItem('token_type',state.token_type)
},
// 退出登录,清除用户数据
outLogin(state:User){
state.token=''
state.userInfo={}
localStorage.setItem('token','')
localStorage.setItem('token_type','')
}
},
//
extraReducers(builder){
// userInfo.fulfilled 函数成功的回调
// 接收两个参数,state为initialState数据,action为返回结果,action.payload拿到返回值
builder.addCase(userInfo.fulfilled,(state,action)=>{
state.userInfo=action.payload // 拿到结果操作store
})
},
})
// 同步方法通过userSlice.actions导出
export const {addUser,getToken,outLogin} = userSlice.actions
// 异步方法 直接导出
export userInfo
// 导出redux:userSlice.reducer
export default userSlice.reducer
在组件中使用
import { outLogin} from '@/store/reducer/user' //导入方法
import { useDispatch, useSelector } from 'react-redux'
import { useNavigate } from 'react-router-dom'
const App= () => {
// 获取redux中user
const user = useSelector(state=>state.user)
// dispatch方法
const dispatch = useDispatch()
const outUser=() => {
// dispatch 调用 outLogin 退出登录
dispatch(outLogin())
navigate('/login')
}
return (<>
<button onClick={outUser}>退出登录</button>
</>)
}
export default App