umi APi
umi/withRouter
Umi@2.x中使用 dva
自>= umi@2
起,dva
的整合可以直接通过 umi-plugin-react 来配置。
特性
- 按目录约定注册 model,无需手动
app.model
- 文件名即 namespace,可以省去 model 导出的
namespace
key - 无需手写 router.js,交给 umi 处理,支持 model 和 component 的按需加载
- 内置 query-string 处理,无需再手动解码和编码
- 内置 dva-loading 和 dva-immer,其中 dva-immer 需通过配置开启
- 开箱即用,无需安装额外依赖,比如 dva、dva-loading、dva-immer、path-to-regexp、object-assign、react、react-dom 等。
yarn add umi-plugin-react
然后在 .umirc.js
里配置插件:
export default {
plugins: [
[
'umi-plugin-react',
{
dva: true,
},
]
],
};
定义 dva model
组件连接dva model
dva-immer
推荐开启 dva-immer 以简化 reducer 编写
export default {
plugins: [
[
'umi-plugin-react',
{
dva: {
immer: true
}
}
],
],
};
开启了 dva-immer
之后,编写 reducers 就方便了:
reducers: {
updateUserList(state, { payload }) {
// return {
// ...state,
// userList: payload
// }
state.userList = payload
},
deleteUser(state, action) {
// return {
// ...state,
// userList: state.userList.filter(user => user.id !== action.id)
// }
state.userList = state.userList.filter(user => user.id !== action.id)
}
},
其实 reducers
可以写得更简单,仅仅写一个 setState
就可以了。dispatch
的时候,表明要改变的 state 即可。put({ type: 'setState', payload: {userInfo: userInfo}})
reducers: {
setState(state, { payload }) {
return {
...state,
...payload
}
},
},
dva-loading 的使用
待异步请求方法成功之后,loading.effects['dvaTest/fetchUserList']
得到 false。
const mapStateToProps = (state) => {
const { loading } = state
return {
// `dvaTest/fetchUserList` 是 model 中异步请求方法
userListLoading: loading.effects['dvaTest/fetchUserList']
}
}
umi2.x 使用mock
在项目根目录添加 mock 文件夹
// mock/users.js
export default {
// 支持值为 Object 和 Array
'GET /api/users': {
name: 'alex.cheng',
avatar: '',
userid: '00000001',
notifyCount: 12,
},
// GET POST 可省略
'/api/users/1': { id: 1 },
// 支持自定义函数,API 参考 express@4
'POST /api/users/create': (req, res) => { res.end('OK'); },
};
使用
fetch('http://recplus-test.jd.com:8000/api/users')
.then(res => {
console.log('????', res)
return res.json()
})
.then(res => {
console.log('res ', res)
})
为了让数据更加丰富,我们可以引入 mockjs
来生成更加全面和丰富的模拟数据。
umi使用动态组件 dynamic
使用 umi 提供的 dynamic 方法,基于 react-loadable 实现。
下面这个例子是:3s 后渲染一个组件,在还未渲染时,通过 loading
方法设置一个 loading
组件。
import dynamic from 'umi/dynamic'
const DynamicComp = dynamic({
loader: () => {
return new Promise(r => {
setTimeout(() => {
r(() => <div>I will render after</div>)
}, 3000);
})
},
loading: () => {
return (
<div>Loading...</div>
)
}
})
umi权限路由
/src/pages/other/index.jsx 文件中,头部的注释是关键。index.jsx
会通过 ./src/routes/auth.jsx
文件来渲染。我们可以在 auth.jsx
中做逻辑处理和判断,决定是否需要渲染index.jsx
组件。
/**
* title: chl other index page
* Routes:
* - ./src/routes/auth.jsx
*/
const Other = function(props) {
return (
<div className={styles.normal}>
<h1>{props.flag}</h1>
<Button onClick={() => setLocale('zh-CN')}>setLocale</Button>
</div>
);
}
export default connect(state => {
return {
flag: state.localModels.key
}
})(Other)
/src/routes/auth.jsx
const Auth = (props) => {
const [show, setShow] = useState(false)
return (
<div>
<Button onClick={() => setShow(!show)}>权限路由</Button>
{show && props.children}
</div>
);
}
export default Auth;