rematch-model-extend v1.0.8
说明
rematch-model-extend主要为了拓展rematch和优化rematch使用体验
安装
npm i rematch-model-extend
优化1
集中收集model,webpack和vite都支持
import { init } from '@rematch/core'
import count from './count.js'
import test from './test.js'
const store = init({
models: {
count,
test
},
})
export default store
每次添加新的model时,都需要手动导入,是否可以通过配置自动导入?答案是可以的
webpack方式
解决:使用rematch-model-extend中的getAllModelsWebpack
- 第一个参数requireContext(必填)支持单个或者数组的方式 -> 使用可以查询require.context
- 第二个参数excludeFileArr(可选)排除某文件的自动收集
- 收集model时,该方法会通过model中的name进行重名提示
import { init } from '@rematch/core'
+ import { getAllModelsWebpack } from 'rematch-model-extend'
const models = getAllModelsWebpack({
requireContext: require.context('../../src', true, /.*\/model(\/.*)*\.js$/),
excludeFileArr: ['./model/index.js']
})
const store = init({
models: models,
})
export default store
vite方式
使用rematch-model-extend中的getAllModelsVite
第二个参数globEager(必填)支持单个或者数组形式
- 第二个参数excludeFileArr(可选)排除某文件的自动收集
import { init } from '@rematch/core'
+ import { getAllModelsVite } from 'rematch-model-extend'
const models = getAllModelsVite({
globEager: [
import.meta.globEager('../../src/**/model/*.js'),
import.meta.globEager('../../src/**/model.js'),
],
excludeFileArr: ['../../src/model/index.js']
})
const store = init({
models: models,
})
优化2
dispatch派发优化
注意:如果是纯ts开发,此优化可以忽略,此设计是为了js和ts混用时开发的
注意:即使effects是函数,其返回值也是可以推断出来的
dispatch({type: 'count/increment', payload: 1})
使用rematch的派发都会遇到这样的问题,需要我们手动拼接type和书写payload,这样写法及其不友好,且没有任何推断
我们可以根据model中reducers和effects推断出其中方法吗?答案是可以的
解决:使用rematch-model-extend中的createAction
model/count.js
+ import { createAction } from 'rematch-model-extend'
const count = {
name: 'count',
state: {
count: 0,
},
reducers: {
increment(state, payload) {
state.count += payload
return state
},
},
effects: {
async incrementAsync(payload, rootState) {
await new Promise(resolve => setTimeout(resolve, 1000))
this.increment(payload)
},
}
}
+ export const Actions = createAction(count)
export default count
app.js
Actions中就是自动推断出model/count模块中的reducers和effects中的方法
+ import { Actions } from './model/count'
+ dispatch(CountActions.increment(1)
优化3
model公共功能合并
注意:即使effects是函数形式,也是可以进行合并的
有这样一种场景:两个model中会有公共的部分,我们是否可以将这些公共的部分进行提取,实现共用?答案是可以的
举例:
model/count.js
import { createAction } from 'rematch-model-extend'
const count = {
name: 'count',
state: {
count: 0,
countRest: 'rest'
},
reducers: {
increment(state, payload) {
state.count += payload
return state
},
handleCount() {
...
}
},
...
}
export const Actions = createAction(count)
export default count
model/test.js
import { createAction } from 'rematch-model-extend'
const test = {
name: 'test',
state: {
count: 0,
testRest: 'rest'
},
reducers: {
increment(state, payload) {
state.count += payload
return state
},
handleTest() {
...
}
},
...
}
export const Actions = createAction(test)
export default test
我们发现count和test中有公共的部分
实现抽离如下:========================>
使用rematch-model-extend中的modelExtend
model/common.js
const common = {
state: {
count: 0
},
reducers: {
increment(state, payload) {
state.count += payload
return state
},
},
}
export default common
model/count.js
import { modelExtend, createAction } from 'rematch-model-extend'
import common from './common'
const count = {
name: 'count',
state: {
testRest: 'rest'
},
reducers: {
handleCount() {
...
}
},
...
}
const model = modelExtend(common, count)
export const Actions = createAction(model)
export default model
model/test.js
import { modelExtend, createAction } from 'rematch-model-extend'
import common from './common'
const test = {
name: 'test',
state: {
testRest: 'rest'
},
reducers: {
handleTest() {
...
}
},
...
}
const model = modelExtend(common, test)
export const Actions = createAction(model)
export default model
其他
项目中可以自行考虑是否使用
rematch-model-extend其他方法:commonModelExtend方法
commonModelExtend中集合了特殊的reducers
如:updateState更新简单类型
如:updateDeepState更新复杂对象类型
如:error更新state中的error属性
如:updateParams更新state中的params属性
感兴趣可以在源码中查找
使用如下
model/example.js
import { commonModelExtend, createAction } from 'rematch-model-extend'
const example = {
name: 'example',
state: {
obj: {
a: {
b: '123'
},
arr: [1, 2, 3],
arr1: [{ id: '1', text: 'name' }]
},
count: 0
},
}
const model = commonModelExtend(example)
export const Actions = createAction(model)
export default model
app.js
import React from 'react'
import { connect } from 'react-redux'
import { Actions } from './model/example'
function App(props) {
return (
<div>
<div>The exampleCount : {props.example.count}</div>
<div>The exampleObj : {JSON.stringify(props.example.obj)} </div>
<div>The exampleArr : {JSON.stringify(props.example.obj.arr)} </div>
<div>The exampleArr : {JSON.stringify(props.example.obj.arr1)} </div>
<div>
<button onClick={() => props.dispatch(Actions.updateState({ count: 1 }))}>updateState</button>
<button onClick={() => props.dispatch(Actions.updateDeepState({ 'obj.a.b': 456 }))}>updateDeepStateObj</button>
<button onClick={() => props.dispatch(Actions.updateDeepState({ 'obj.arr.1': 5 }))}>updateArr</button>
<button onClick={() => props.dispatch(Actions.updateDeepState({ 'obj.arr': null }))}>deleteArr</button>
<button onClick={() => props.dispatch(Actions.updateDeepState({ 'obj.arr1.id_1.text': 'zs' }))}>updateDeepStateArr1</button>
<button onClick={props.dispatch}>toCountIncrement</button>
</div>
</div>
);
}
const mapState = state => ({
example: state.example
})
export default connect(mapState)(App);