页面跟数据是分开写的
demo1
list.js 页面
import React, { useEffect, useRef } from 'react';
import { connect } from 'dva';
import { Form, Input, Button } from 'antd';
const List = props => {
console.log(props);
const { dispatch, book } = props;
const { list } = book;
const name = useRef();
useEffect(() => {
dispatch({
type: 'book/loadData',
});
}, []);
return (
<div>
我是一个列表页
<Form>
<Form.Item name="name">
<Input ref={name} placeholder="请输入名字" />
</Form.Item>
<Form.Item>
<Button
type="danger"
onClick={() => {
// console.log(name.current.state.value);
// console.log('点击了');
// 调用save方法只需要用 dispatch type类型为 namespace(book) 和自定义方法名(save) payload 传递改变的参数
dispatch({
type: 'book/save',
payload: {
list: [...list, { id: Date.now(), name: name.current.state.value }],
},
});
}}
>
保存
</Button>
</Form.Item>
</Form>
{list.map(item => (
<p key={item.id}>{item.name}</p>
))}
</div>
);
};
const mapStateToProps = state => ({
book: state.book,
});
export default connect(mapStateToProps)(List);
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State,所以在 dva 中,数据流向非常清晰简明,并且思路基本跟开源社区保持一致(也是来自于开源社区)。
book.js 数据页
export default {
namespace: 'book',
state: {
list: [],
page: 1,
current: {},
},
effects: {
*loadData({ payload }, { call, put }) {
//
yield put({
type: 'save',
payload: {
list: [
{ id: 1, name: '球状闪电' },
{ id: 2, name: '沙丘' },
],
},
});
},
},
reducers: {
save(state, { payload }) {
return { ...state, ...payload };
},
},
};
demo2
index.js 页面
import React, { useEffect } from 'react';
import { connect } from 'dva';
import styles from './index.css'; // css module 样式模块化,把样式文件解析成一个对象
export default connect(state => state.movie)(function(props) {
console.log(props);
const { dispatch, list, page } = props;
useEffect(() => {
dispatch({
type: 'movie/loadData',
payload: {
page,
},
});
}, []);
return (
<div className={styles.normal}>
<div className={styles.welcome} />
<ul className={styles.list}>
{list.map(item => (
<li key={item._id}>{item.title}</li>
))}
</ul>
<button
onClick={() => {
dispatch({
type: 'movie/loadData',
payload: {
page,
},
});
}}
>
加载更多
</button>
</div>
);
});
movie.js 数据页
import { loadDataFromServer } from '../services/movies';
export default {
namespace: 'movie',
state: {
list: [],
page: 1,
},
effects: {
*loadData({ payload }, { call, put }) {
const { page } = payload;
const res = yield call(loadDataFromServer, page); // 调用接口获取数据数据
yield put({
type: 'loadDataEnd',
payload: {
list: res.books,
page: page + 1,
},
});
},
},
reducers: {
save(state, { payload }) {
return { ...state, ...payload };
},
loadDataEnd(state, { payload }) {
return { ...state, list: [...state.list, ...payload.list], page: payload.page };
},
},
};