一、安装依赖
笔者版本: react版本 17.0.2 redux 4.0.5
虽然react也可以使用npm, 但是react官方主要是使用yarn管理包的,推荐大家也可以了解下,学习成本不高
yarn add redux
笔者的redux实践可以和常规的有些不同,先列出文件结构,后面会说明原因。
二、创建reducers
这里的store就是redux实际应用的文件了,和Vuex的状态管理文件创建的文件夹是store是意义的
课外小知识: store本意也有存储的意思,所以语义化更强[点赞]
redux在reduce人中可以单独创建数据存储对象,所以并不是一定需要通过state.js文件
// /store/reducers/mainReducer.js
import {combineReducers} from redux; // 用于合并多个reducer文件,便于管理的
import banner from './bannerReducer.js';
import user from './userReducer.js';
// 经过实践,笔者发现在使用时如果调用的是state.js存储数据,会同时返回两次,
// 所以在reducers文件中各自创建了数据对象,便于分开管理。
const reducer = combineReducers({
bannerState: bannerReducer,
userState: userReducer
})
export default reducer;
// /store/reducers/userReducer.js
const defaultState = { // 这个常量名没什么特别含义, 大家自己开心就好
loginStatus: false
}
// 喜欢用state.js可以这样引入,在下面会提到state.js的创建
import defaultState from '../state.js';
function loginOut(state = defaultState.loginStatus, action){
// 最终返回给调用的数据, 两种写法取其一
return Object.assign([], state, action.data,{
userInfo: ''
})
return Object.assign([], state, action.data)
}
export default function userReducer(state = defaultState, action){
// 根据传递的type调用对应的方法。
switch(action.tyoe){
case 'LOGIN_OUT':
return loginOut(action.data);
default:
return state;
}
}
三、创建action.js
如果只是少量的状态管理,是可以不要这个文件的,在下面会提到不通过action方法调用reducer
export function user(type, data){
switch(type){
case 'Login_out':
return {
type: 'LOGIN_OUT',
data: data
}
case 'LOGIN_IN':
return {
type: 'LOGIN_IN',
data: data
}
}
}
四、创建index.js
这个文件创建好了,就不用管了,轻松愉快
import {createStore} from 'redux';
import reducers from './reducers/mainReducer';
let store = createStore(reducers);
export default store;
五、创建state.js(可选)
如果创建state.js的话, 在reducer文件中引入并删除掉前面写的defaultState对象即可
但是前面也说了,类似我这种多个功能需要用到状态管理的, 在reducer中分别管理各自的state比较好处理点。
export default {
loginStatue: false,
showBanner: false
}
六、代码中调用redux
话不多说,开搞。
根据@一条鱼的心事大佬在评论区指出的关于订阅store的问题,这里我将两点都写出来,供大家参考,选择使用
如果不需要在当前界面针对store的修改做出变化是可以不用订阅store的state信息的。
import store from '../../store/index';
import {user} from '../../store/action';
constructor(props){
super(props);
// 订阅(监听)store值的变化,除非当前界面内会修改,否则是不需要写的
store.subscribe(() => {
this.setState({
loginStatue: store.getState().userState['loginStatus']
})
})
}
componentDidMount(){
// 调用action方法 -> 返回参数传给mainReducers -> 根据type找到对应的reducer方法
store.dispatch(user('LOGIN_OUT', false}))
// 直接调用mainReducers -> 根据type找到对应的reducer方法
store.dispatch({type:'LOGIN_OUT', data: false})
},
// 使用订阅方法之后需要在组件卸载前前进行手动注销
componentWillUnmount(){
store.unsubscribe();
}
来自一条鱼的心事大佬给出的最佳实践写法
// /src/Index.js;
// 在index.js文件处讲store方法挂载在root上,方便调用;
import store from './store/index';
window.$dispatch = store.dispatch;
window.$getState = store.getState;
// /src/pages/view.js;
import store from '../../store/index';
import {user} from '../../store/action';
import {connect, mapStateToProps} from 'react-redux';
class View extends Component{
function mapStateToProps(state){
return {
loginStatus: $getState().user.loginStatus
}
}
render(){
return (
<div>略</div>
)
}
}
export default connect(mapStateToProps)(View);
七、总结
这是我踩坑之后找到的比较简单灵活的redux调用方法, 如果还有更简单的希望能在评论区丢个链接。
最开始我看到一个使用成本很高的redux教程,差点弃坑滚回Vue了。
学习的路还长,一定要坚持下去。
希望觉得不错的看官给个赞支持下。谢谢