都知道vuejs里面帮我们实现了一个内置的keep-alive
组件,给我们缓存一些组件的状态带来了很大的便利。但是在react中没有自带的实现,可以借助社区的插件umi-plugin-keep-alive
来实现这个功能。
实现效果对比
- 未使用插件,可以看到我们在页面跳出去再返回的时候,之前的状态丢失了
- 使用了插件后的效果,页面跳转数去后再返回,表单个table分页都是跳出去时的状态。这个需求在vuejs中是可以直接使用keep-alive组件的。react中我们使用
umi-plugin-keep-alive
实现
安装
npm i umi-plugin-keep-alive
注册
config/config.ts中添加下面的代码,不然不生效。
plugins: ['umi-plugin-keep-alive'],
使用
在注册之后,才可以从umi
中导出这个组件,来包裹我们需要缓存的组件,且根元素只能有一个,否则会报错。
这些是我们可以使用的全部的钩子,自动给我们配置好了,需要使用直接引入就行。
import { Button, Space, Table, Form, Input,Image} from 'antd'
import type { TableColumnsType, TableProps } from 'antd';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import React from 'react'
import { connect } from '@umijs/max';
import { KeepAlive,useModel,history } from 'umi'
import type { Settings as LayoutSettings } from '@ant-design/pro-components';
type NameType = {name:string,age:number,address?:string,
}
interface DemoProps {user:NameType,add:()=>void,minus:()=>void,asyncAdd:()=>void,count:number,msg:string,
}interface CountType {count:number
}interface DataType {key: React.Key;name: string;age: number;address: string;
}type TableRowSelection<T extends object = object> = TableProps<T>['rowSelection'];const columns: TableColumnsType<DataType> = [{ title: 'Name', dataIndex: 'name' },{ title: 'Age', dataIndex: 'age' },{ title: 'Address', dataIndex: 'address' },
];const dataSource = Array.from<DataType>({ length: 46 }).map<DataType>((_, i) => ({key: i,name: `Edward King ${i}`,age: 32,address: `London, Park Lane no. ${i}`,
}));
const DemoPage:React.FC<DemoProps> = (props) => {console.log("🚀 ~ props:", props)const { msg,user,add,count: num,minus,asyncAdd } = propsconst [count, setCount] = React.useState(0)const [isShow, setIsShow] = React.useState(true)const [selectedRowKeys, setSelectedRowKeys] = React.useState<React.Key[]>([]);const [form] = Form.useForm();const [clientReady, setClientReady] = React.useState<boolean>(false);const {initialState} = useModel('@@initialState')const handleAdd:() => void = () => {setCount(count + 1)add()}const handleMinus:() => void = () => {setCount(count - 1)minus()}const handleSetState:() => void = () => {console.log('setstate')setIsShow(!isShow)}const onSelectChange = (newSelectedRowKeys: React.Key[]) => {setSelectedRowKeys(newSelectedRowKeys);};const rowSelection: TableRowSelection<DataType> = {selectedRowKeys,onChange: onSelectChange,};const onFinish = (values: any) => {console.log('Finish:', values);};const handleAddAsync = () => {asyncAdd()}// record的类型const handleClick = (item: DataType) => {console.log('click ', item);history.push(`/admin/sub-page`);};return <div><h2>Demo Page</h2>{/* <p><Image src={initialState?.settings?.logo}/></p> */}{selectedRowKeys.length > 0 && <span>Selected: {selectedRowKeys.length}</span>}{/* <div><p>{msg}</p><p>{user.name + '---------' + user.age}</p><p>dva里面的num:{num}</p><Space><Button type="primary" onClick={handleAdd}>add</Button><Button type="primary" danger onClick={handleMinus}>minus</Button><Button type="primary" onClick={handleAddAsync}>addAsync</Button></Space></div> */}<KeepAlive><Form form={form} name="horizontal_login" layout="inline" onFinish={onFinish}><Form.Itemname="username"rules={[{ required: true, message: 'Please input your username!' }]}><Input prefix={<UserOutlined />} placeholder="Username" /></Form.Item><Form.Itemname="password"rules={[{ required: true, message: 'Please input your password!' }]}><Input prefix={<LockOutlined />} type="password" placeholder="Password" /></Form.Item><Form.Item shouldUpdate>{() => (<Buttontype="primary"htmlType="submit">Log in</Button>)}</Form.Item></Form><Table rowSelection={rowSelection} columns={columns} dataSource={dataSource} onRow={(record) => {return {onClick: (event) => {handleClick(record);}, // 点击行onDoubleClick: (event) => {},onContextMenu: (event) => {},onMouseEnter: (event) => {}, // 鼠标移入行onMouseLeave: (event) => {},};}}/></KeepAlive></div>
}const Counter:React.FC<CountType> = (props) => {// const { count } = propsconst [count, setCount] = React.useState(0)const handleAdd:() => void = () => {setCount(count + 1)}return <div><p>{count}</p><Button type="primary" onClick={handleAdd}>add</Button></div>}const mapStateToProps = (state:any) => {console.log("🚀 ~ mapStateToProps ~ state:", state)return {user: state.userModel.user,count: state.userModel.count}
}const mapToDispatchToProps = (dispatch:any) => {return {add: () => dispatch({ type: 'userModel/add', payload: 4 }),minus: () => dispatch({ type: 'userModel/minus', payload: 4 }),asyncAdd: () => dispatch({ type: 'userModel/asyncAdd',payload:20 })}}export default connect(mapStateToProps,mapToDispatchToProps)(DemoPage)
结尾
其他的钩子可以去尝试下效果,基本就跟vuejs
里面一样使用了,有监听创建销毁组件。