一.redux使用
1.安装
npm i redux
例一:
2.创建redux文件夹,store.js文件
store.js文件
import {legacy_createStore as createStore,combineReducers}from "redux"
// 每一块状态内容对应一个reducer文件
import {CollApsedReducer} from "./CollapsedReducer"
import {LoadingReducer}from "./LoadingReducer"
// combineReducers合并多个reducer
const reducer=combineReducers({
CollApsedReducer,
LoadingReducer
})
// createStore里面只能放一个reducer,所以上面合并处理一下
const store=createStore(reducer)
export default store
3.将提供者绑定到跟组件内外层,使每个被包裹的组件都可以使用store
import React from 'react';
import IndexRouter from "../src/router"
import {Provider}from "react-redux"
import store from "../src/redux/store"
function App() {
return (
<Provider store={store}>
<IndexRouter />
</Provider>
);
}
export default App;
4.更改状态
import React , { useState }from 'react'
import { Layout,Button ,Avatar, Space,Dropdown } from 'antd';
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
UserOutlined
} from '@ant-design/icons';
import { useHistory } from 'react-router-dom'
import {connect}from "react-redux"
const { Header } = Layout;
// 接收props并使用
function TopHeader(props) {
console.log(props);
// const [collapsed, setCollapsed] = useState(false);
const history = useHistory()
const isCollapsed=()=>{
props.changeCollapsed()
}
const items = [
{
key: '1',
primary: true,
label: '超级管理员',
},
{
key: '2',
danger: true,
label: '退出登录',
},
];
const onClick = ({ key }) => {
if(key==="2"){
localStorage.removeItem("token")
history.push({pathname: '/login'})
}
};
return (
<Header style={{ padding: 0, }}>
<Button
type="text"
// 使用仓库的折叠状态
icon={props.isCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
// 更改action
onClick={()=>isCollapsed()}
style={{
fontSize: '16px',
width: 64,
height: 64,
}}
/>
<div style={{float:'right',marginRight:"20px"}}>
<span style={{marginRight:"20px"}}>欢迎admin回来</span>
<Dropdown menu={{ items,
onClick
}}>
<a onClick={(e) => e.preventDefault()}>
<Space>
<Avatar size="large" icon={<UserOutlined />} />
</Space>
</a>
</Dropdown>
</div>
</Header>
)
}
// 更新props
const mapStateToProps=({CollApsedReducer:{isCollapsed}})=>{
return{
isCollapsed
}
}
// 更新action
const mapDispatchToProps={
changeCollapsed(){
return {
type:"change_collapsed"
}
}
}
// connect()(组件名)
// connect函数将组件连接到store仓库
export default connect(mapStateToProps,mapDispatchToProps)(TopHeader)
5.使用状态变化的组件
import React, { useState, useEffect } from 'react';
import { useHistory, withRouter } from 'react-router-dom';
import { Layout, Menu } from 'antd';
import { UserOutlined, DesktopOutlined, FileOutlined, PieChartOutlined, TeamOutlined } from '@ant-design/icons';
import "../newssandbox/index.css";
// 引入connect
import {connect}from "react-redux"
const { Sider } = Layout;
const { SubMenu } = Menu;
function SideMenu(props) {
// props接收
const [selectedKey, setSelectedKey] = useState(null);
const select=[props.location.pathname.split("/")[1]]
const history = useHistory();
const onClick = (e) => {
history.push(e.key);
};
useEffect(() => {
// 根据路由变化更新选中的菜单项
const currentPath = props.location.pathname;
setSelectedKey(currentPath);
}, [props.location.pathname]);
function renderMenuItems(items) {
return items.map((item) => {
if (item.children) {
return (
<SubMenu key={item.key} icon={item.icon} title={item.label}>
{renderMenuItems(item.children)}
</SubMenu>
);
} else {
return (
<Menu.Item key={item.key} icon={item.icon}>
{item.label}
</Menu.Item>
);
}
});
}
const items = [
{
key: '/home',
label: '首页',
icon: <PieChartOutlined />,
},
{
key: 'user-manage',
label: '用户管理',
icon: <DesktopOutlined />,
children: [
{ key: '/user-manage/list', label: '用户列表', icon: <DesktopOutlined /> }
],
},
{
key: 'right-manage',
label: '权限管理',
icon: <UserOutlined />,
children: [
{ key: '/right-manage/role/list', label: '角色列表' },
{ key: '/right-manage/right/list', label: '权限列表' }
],
},
{
key: 'news-manage',
label: '新闻管理',
icon: <TeamOutlined />,
children: [
{ key: '/news-manage/add', label: "撰写新闻" },
{ key: '/news-manage/draft', label: '草稿箱' },
{ key: '/news-manage/category', label: '新闻分类' }
],
},
{
key: 'audit-manage',
label: '审核管理',
icon: <FileOutlined />,
children: [
{ key: '/audit-manage/audit', label: "审核新闻" },
{ key: '/audit-manage/list', label: '审核列表' },
],
},
{
key: 'publish-manage',
label: '发布管理',
icon: <FileOutlined />,
children: [
{ key: '/publish-manage/unpublished', label: "待发布" },
{ key: '/publish-manage/published', label: '已发布' },
{ key: '/publish-manage/sunset', label: '已下线' }
],
},
];
return (
<div>
{/* props.isCollapsed使用 */}
<Sider trigger={null} collapsible collapsed={props.isCollapsed}>
<div className="demo-logo-vertical">全球新闻发布管理系统</div>
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['home']}
selectedKeys={[selectedKey]}
defaultOpenKeys={select}
onClick={onClick}
>
{renderMenuItems(items)}
</Menu>
</Sider>
</div>
);
}
// {CollApsedReducer:{isCollapsed}}CollApsedReducer reducer文件导出的变量名,isCollapsed状态,此处进行解构
const mapStateToProps=({CollApsedReducer:{isCollapsed}})=>{
return{
isCollapsed
}
}
export default connect(mapStateToProps)(withRouter(SideMenu));
例二:
1.新建LoadingReducer.js文件
export const LoadingReducer=(prevState={
loading:false
},action)=>{
let {type,payload}=action
switch (type) {
case 'change_loading':
// 复制老状态,不可直接修改
let newState={...prevState}
newState.loading=payload
return newState
default:
return prevState
}
}
2.路由文件
import React from 'react'
import {Route,Switch,Redirect}from "react-router-dom"
import Home from "../../views/newssandbox/home/Home"
import UserList from "../../views/newssandbox/user-mange/UserList"
import RoleList from"../../views/newssandbox/right-manage/RoleList"
import RightList from"../../views/newssandbox/right-manage/RightList"
import NoPermission from "../../views/newssandbox/nopermission/Nopermission"
import NewsAdd from "../../views/newssandbox/news-manage/NewsAdd"
import NewsDraft from "../../views/newssandbox/news-manage/NewsDraft"
import NewsCategory from "../../views/newssandbox/news-manage/NewsCategory"
import AuditManage from "../../views/newssandbox/audit-manage/AuditManage"
import AuditList from "../../views/newssandbox/audit-manage/AuditList"
import Unpublished from "../../views/newssandbox/publish-manage/Unpublished"
import Publishedd from "../../views/newssandbox/publish-manage/Publishedd"
import Sunset from "../../views/newssandbox/publish-manage/Sunset"
import { Spin } from 'antd';
import {connect}from "react-redux"
function NewsRouter(props) {
return (
<div>
{/* 为每个页面使用loading功能 */}
<Spin size="large" style={{marginTop:"200px"}} spinning={props.loading} >
<Switch>
<Route path="/home" component={Home}/>
<Route path="/user-manage/list" component={UserList}/>
<Route path="/right-manage/role/list" component={RoleList}/>
<Route path="/right-manage/right/list" component={RightList}/>
<Route path="/news-manage/add" component={NewsAdd}/>
<Route path="/news-manage/draft" component={NewsDraft}/>
<Route path="/news-manage/category" component={NewsCategory}/>
<Route path="/audit-manage/audit" component={AuditManage}/>
<Route path="/audit-manage/list" component={AuditList}/>
<Route path="/publish-manage/unpublished" component={Unpublished}/>
<Route path="/publish-manage/published" component={Publishedd}/>
<Route path="/publish-manage/sunset" component={Sunset}/>
{/* 如果访问根路径回车精确匹配重定向到home页面 */}
<Redirect from="/" to="/home" exact/>
{/* 如果是随便输入或除了以上路径的其他路径显示404页面 */}
<Route path="*" component={NoPermission}/>
</Switch>
</Spin>
</div>
)
}
const mapStateToProps=({LoadingReducer:{loading}})=>{
return{
loading
}
}
const mapDispatchToProps={
changeCollapsed(){
return {
type:"change_loading"
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(NewsRouter)
3.在axios封装文件内使用
import axios from "axios";
import store from "../redux/store";
axios.defaults.baseURL = "http://localhost:3000";
axios.interceptors.request.use(
(config) => {
// 显示loading
store.dispatch({
type: "change_loading",
payload: true,
});
return config;
},
(error) => {
return Promise.reject(error);
}
);
axios.interceptors.response.use(
(response) => {
// 隐藏loading
store.dispatch({
type: "change_loading",
payload: false,
});
return response;
},
(error) => {
// 隐藏loading
store.dispatch({
type: "change_loading",
payload: false,
});
return Promise.reject(error);
}
);
export default axios;
二.持久化
1.安装
npm i redux-persist
2.store.js文件配置持久化
import {legacy_createStore as createStore,combineReducers}from "redux"
import {CollApsedReducer} from "./CollapsedReducer"
import {LoadingReducer}from "./LoadingReducer"
//配置数据的持久化效果
import { persistReducer, persistStore } from "redux-persist";
//导入需要配置的数据源,可以选择,storage,cookie,session等
import storage from "redux-persist/lib/storage";
const reducer=combineReducers({
CollApsedReducer,
LoadingReducer
})
//定义配置的信息
const persitConfig = {
// 代表存储名,随便起
key:"root",
storage,
// 如果不想将部分state持久化,也可以将其放入黑名单(blacklist)中,白名单whitelist
// 将loading 模块不做持久化
blacklist:["LoadingReducer"]
}
//创建持久化的配置persist的信息
const persistReducers = persistReducer(persitConfig,reducer);
//创建存储对象并且抛出对象
const store=createStore(persistReducers)
const persistor =persistStore(store);
export{store,persistor}
3.仓库导出方式更改了,组件引入方式要改变
4.根组件内使用PersistGate文章来源:https://uudwc.com/A/jVXwN
import React from 'react';
import IndexRouter from "../src/router"
import {Provider}from "react-redux"
import {store,persistor} from "../src/redux/store"
// 在入口文件中使用 PersistGate 包裹根组件。将延迟渲染app 视图直到持久化状态取回并保存到redux中
import {PersistGate}from "redux-persist/integration/react"
function App() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<IndexRouter />
</PersistGate>
</Provider>
);
}
export default App;
文章来源地址https://uudwc.com/A/jVXwN