目录
扩展学习资料
Reselect【数据持久化】&Immutable Data【不变数据】方案【解决某些场景重复渲染,重复计算的问题】
@/src/reducer/index.js
Reselect【 可缓存的筛选项,当数据量大的时候,可以节省diff时间,提升渲染效率】
@src/reducer/reselect/index.js
@/src/actions/reselect/index.js
@/src/containers\reselect\index.jsx
@/src/store/index.js
Immutable Data
Immutable方案
@/src/containers/immutable/index.jsx
@/src/actions/immutable/index.js
@/src/reducer/immutable/index.js
redux-actions & @rematch/core & dva【比较高阶状态管理方案】
@/src/actions/redux-actions/index.js
@/src/containers/redux-actions/index.jsx
@/src/reducer/redux-actions/index.js
Reudx的不足
redux-actions & @rematch/core & dva
名称 |
链接 |
备注 |
redux-actions |
Introduction - redux-actions |
英文 |
@rematch/core |
Rematch | Rematch |
|
dva |
介绍 | DvaJS |
import { combineReducers } from 'redux';
import homeReducer from './home';
import reSelectReducer from './reselect';
import immutableReducer from './immutable';
import reduxActionsReducer from './redux-actions';
// console.log(reSelectReducer());
// 合并多个reducer
// 扩展性
export default combineReducers({
homeReducer,
reSelectReducer,
immutableReducer,
reduxActionsReducer,
});
import * as types from '@/actions/mutation-types';
const initialState = {
reSelectList: [{
key: '001',
status: true,
name: 'flex-reselect-1',
}, {
key: '002',
status: true,
name: 'flex-reselect-2',
}, {
key: '003',
status: false,
name: 'flex-reselect-3',
}, {
key: '004',
status: true,
name: 'flex-reselect-4',
}, {
key: '005',
status: false,
name: 'flex-reselect-5',
}, {
key: '006',
status: false,
name: 'flex-reselect-6',
}, {
key: '007',
status: true,
name: 'flex-reselect-7',
}],
filterStatus: 'FILTER_ALL_DATA',
};
const mutations = {
[types.FILTER_ALL_DATA](state) {
return { ...state };
},
[types.UPDATE_FILTER_STATUS](state, action) {
return {
...state,
filterStatus: action.payload,
};
},
};
export default function (state = initialState, action) {
if (!mutations[action.type]) return state;
return mutations[action.type](state, action);
}
import * as types from '../mutation-types';
export function filterData(data, filter) {
console.log(filter, 'filter', Date.now());
switch (filter) {
case types.FILTER_ALL_DATA:
return data;
case types.FILTER_SUCCESS_STATUS:
return data.filter(item => item.status);
case types.FILTER_FAIL_STATUS:
return data.filter(item => !item.status);
default:
return data;
}
}
export function updateFilterStatus(params) {
return {
type: types.UPDATE_FILTER_STATUS,
payload: params,
};
}
import React, { Component } from 'react';
import propTypes from 'prop-types';
import { connect } from 'react-redux';
// 可缓存的筛选项,当数据量大的时候,可以节省diff时间,提升渲染效率
import { createSelector } from 'reselect';
import {
filterData,
updateFilterStatus,
} from '@/actions/reselect';
const filterStatusMap = {
1: 'FILTER_ALL_DATA',
2: 'FILTER_SUCCESS_STATUS',
3: 'FILTER_FAIL_STATUS',
};
const getReselectList = (state) => state.reSelectReducer.reSelectList;
const getFilterStatus = (state) => state.reSelectReducer.filterStatus;
// 一个可以缓存的数据源,避免了数据的重复计算,和页面更新
const filterReselectData = createSelector(
[getReselectList, getFilterStatus],
(list, filter) => filterData(list, filter),
);
// filterData(
// state.reSelectReducer.reSelectList,
// state.reSelectReducer.filterStatus,
// )
@connect(
(state) => ({
filterList: filterReselectData(state),
}),
(dispatch) => ({
updateFilterStatus: (params) => dispatch(updateFilterStatus(params)),
}),
)
export default class ReselectDemo extends Component {
handleUpdate = (signal) => {
const { updateFilterStatus } = this.props;
updateFilterStatus(filterStatusMap[signal]);
// console.log(signal, this.props, updateFilterStatus);
}
render() {
const { filterList } = this.props;
return (
<>
{filterList.map(item => (
{item.name}
{String(item.status)}
))}
>
);
}
}
ReselectDemo.propTypes = {
filterList: propTypes.arrayOf(propTypes.object),
updateFilterStatus: propTypes.func,
};
ReselectDemo.defaultProps = {
filterList: [],
updateFilterStatus: () => null,
};
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from '@/reducer';
const middlewares = [thunk];
// 配合浏览器安装的redux开发者工具
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default createStore(
reducers,
composeEnhancers(applyMiddleware(...middlewares)),
);
immutable.js
immer.js【让状态可追溯、避免副作用、纯函数,大型项目必备,避免一些不必要的问题:健壮性,维护问题】
import React, { Component } from 'react';
import { connect } from 'react-redux';
import propTypes from 'prop-types';
import updateImmutableData from '@/actions/immutable';
@connect(
(state) => {
console.log(state.immutableReducer);
return ({
complexData: state.immutableReducer.complexData,
});
},
(dispatch) => ({
updateImmutableData: (params) => dispatch(updateImmutableData(params)),
}),
)
export default class ImmutableDemo extends Component {
handleClick = () => {
const { updateImmutableData } = this.props;
updateImmutableData('immutable 云');
}
render() {
const { complexData } = this.props;
return (
{complexData?.commonInfo?.name?.firstName}
);
}
}
ImmutableDemo.propTypes = {
complexData: propTypes.objectOf(propTypes.object),
updateImmutableData: propTypes.func,
};
ImmutableDemo.defaultProps = {
complexData: {},
updateImmutableData: () => null,
};
import * as types from '../mutation-types';
export default function updateImmutableData(params) {
return {
type: types.UPDATE_IMMUTABLE_DATA,
payload: params,
};
}
import produce from 'immer';
import * as types from '@/actions/mutation-types';
const initialState = {
complexData: {
commonInfo: {
name: {
firstName: '云',
secondName: 'Fedora',
},
},
specialInfo: {
address: '网商路24599号',
},
},
};
const mutations = {
[types.UPDATE_IMMUTABLE_DATA](state, action) {
return produce(state, draftState => {
// eslint-disable-next-line no-param-reassign
draftState.complexData.commonInfo.name.firstName = action.payload;
console.log('oldState', state);
});
// const { complexData } = state;
// const newComplexData = { ...complexData };
// newComplexData.commonInfo.name.firstName = action.payload;
// 改变了源,产生了副作用,无法回溯
// console.log('newComplexData Vs complexData', newComplexData, complexData);
// return {
// ...state,
// complexData: newComplexData,
// };
},
};
export default function (state = initialState, action) {
if (!mutations[action.type]) return state;
return mutations[action.type](state, action);
}
Redux扩展&更多状态管理方案
import * as types from '../mutation-types';
export default function updateReduxActions(params) {
return {
type: types.UPDATE_REDUX_ACTIONS_DATA,
payload: params,
};
}
import React, { Component } from 'react';
import { connect } from 'react-redux';
import propTypes from 'prop-types';
@connect((state) => state.reduxActionsReducer)
export default class ReduxActionsDemo extends Component {
render() {
const { actionName } = this.props;
return (
{actionName}
);
}
}
ReduxActionsDemo.propTypes = {
actionName: propTypes.string,
};
ReduxActionsDemo.defaultProps = {
actionName: '',
};
import * as types from '@/actions/mutation-types';
const initialState = {
actionName: '云',
};
const mutations = {
[types.UPDATE_REDUX_ACTIONS_DATA](state, action) {
return {
...state,
actionName: action.payload,
};
},
};
export default function (state = initialState, action) {
if (!mutations[action.type]) return state;
return mutations[action.type](state, action);
}
旧的react项目redux解决多层范式问题建议使用redux-actions;e
新的react项目建议使用dva或@rematch/core是比较成熟的框架;有中文文档
选择技术方案的着重点:
1.接入成本:学习的曲线
2.改造成本:使用后,团队的是否接受,收益是什么,纯技术类还是包含产品类
3.团队方案:社区是否完善【市场层面,学习圈层面是否足够大】,技术栈是否贴合【与我们团队的技术栈是否贴合】