redux-persist 必须要与react-redux配合使用,才能实现数据持久化
note: 先将store和中间件都创建好,然后直接按照文档使用redux-persisit就好
App.js
import { HashRouter as Router, Switch, Route } from 'react-router-dom'
import Layout from './view/Layout'
import Login from './view/Login'
// 通过redux创建的store
import { store, persistor } from './store'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
export default function App() {
return (
// 通过react-redux的Provider向全局提供一个store
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<Router>
<Switch>
<Route path="/login" component={Login} />
<Route path="/" component={Layout} />
</Switch>
</Router>
</PersistGate>
</Provider>
)
}
src/store/index.js 这里先把store的逻辑写清楚,再照着redux-persist的文档把持久化配置加进去就好了
import { createStore, combineReducers, applyMiddleware } from 'redux'
import reactPromise from 'redux-promise'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
const initState1 = {
login: false,
}
const initState2 = {
username: ''
}
const reducer1 = (state = initState1, action) => {
const newState = {...state}
switch (action.type) {
case 'login':
newState.login = action.login;
return newState
default:
return state
}
}
const reducer2 = (state = initState2, action) => {
const newState = {...state}
switch (action.type) {
case 'username':
newState.username = action.username
return newState
default:
return state
}
}
const persistConfig = {
key: 'userinfo',
storage,
}
const reducers = combineReducers({logininfo: reducer1, userinfo: reducer2})
const persistedReducer = persistReducer(persistConfig, reducers)
const store = createStore(persistedReducer, applyMiddleware(reactPromise))
const persistor = persistStore(store)
export { store, persistor }
src/view/login.js
import { useState } from 'react'
import { connect } from 'react-redux'
function Login(props) {
const [username, setUsername] = useState('')
const [password, setPs] = useState('')
const changeUsername = (ev) => {
setUsername(ev.target.value)
}
const changePs = (ev) => {
setPs(ev.target.value)
}
const loginHandle = () => {
if (!(username && password)) return alert('用户名或者密码不能为空')
props.history.push('/')
props.login({
type: 'login',
login: true
})
props.setName({
type: 'username',
username
})
}
return (
<div>
<input value={username} onChange={ (ev) => changeUsername(ev) } placeholder='请输入用户名' />
<input type="password" value={password} onChange={ (ev) => changePs(ev) } placeholder='请输入密码' />
<button onClick={ loginHandle }>登 录</button>
</div>
)
}
const mapDispatchToProps = {
login(obj) {
return {
...obj
}
},
setName(nameinfo) {
return {
...nameinfo
}
}
}
export default connect(null, mapDispatchToProps)(Login)
src/view/Layout.js (里面还有一个/list 和 /detail 页面就不展示了)
import List from './Layout/List'
import Detail from './Layout/Detail'
import { Switch, Route, Redirect } from 'react-router-dom'
import { connect } from 'react-redux'
const routesConfig = [
{
path: '/list',
component: List
},
{
path: '/Detail/:id',
component: Detail
}
]
function Layout(props) {
const { isLogin, username } = props;
return (
<>
<h4>用户名:{username}</h4>
<button onClick={() => {
// 第一个参数是设置login为false,第二个参数是把username置为空
// 组件中直接调用映射的函数即可
// props.clearLogin(false)
// props.clearUsername('')
props.history.push('/login')
localStorage.clear()
}}>退出</button>
<Switch>
{
routesConfig.map(item => isLogin ? <Route key={item.path} {...item} /> : <Redirect key={item.path} to="/login" />)
}
{ isLogin && <Redirect from="/" to={routesConfig[0].path} /> }
</Switch>
</>
)
}
// 映射store中的state到组件的props
const mapStateToProps = (state) => ({
isLogin: state.logininfo.login,
username: state.userinfo.username
})
// 映射dispatch到组件的props
const mapDispatchToProps = {
clearLogin(loginstatus) {
return {
type: 'login',
login: loginstatus
}
},
clearUsername(username) {
return {
type: 'username',
username
}
}
}
// connect是一个高阶函数介绍两个参数,第一个是一个函数,第二个是一个对象
export default connect(mapStateToProps, mapDispatchToProps)(Layout)