最近在dva+umi中 引用redux 和hook 封装一个table请求……

1,151 阅读2分钟

有好几个月没有接触react了,最近突然发现react项目方法 很流行用typescript方法来写,我就……,做前端太难了,技术一个接一个。

最近研究的是 关于 redux封装一个 table请求函数  还有用hook封装table请求方法这二者有啥不同。

首先先分析要实现的事情

视图层

一个table视图 需要传进去 pagesize,pagenum, total, data, loading 这些最基本的数据,

获取这些数据 要基于fetch请求

1、使用dva redux封装的请求插件 代码如下

import { request, postData } from '../util/request'
export default {
    namespace: 'poemTable',
    state: {
      data: [],
      pageNum: 1,
      pageSize: 10,
      total: 0,
      loading: false 
    },
    effects: {
      *queryInitPoems(_, sageEffects) {
        const { payload, callback} = _;
        const { call, put } = sageEffects;
        const { url, params} = payload;
        let { pageSize, pageNum } = params;
        yield put({ type: 'setLoad', payload: true});
        yield put({ type: 'setPageInit',
          payload: { pageSize, pageNum }
        });
        const res = yield call(postData, url, params);
        yield put({ type: 'getList', payload: res});
        yield put({ type: 'setLoad', payload: false});
        if (callback) {
          callback(res);
        };
      }
    },
    reducers: {
      getList(state, { payload: resData }) {
        return {
          data: resData.data.list || [],
          total: resData.data.count
        };
      },
      setLoad(state, { payload: loadstate}) {
        return {
          ...state,
          loading: loadstate
        }
      },
      setPageInit(state, { payload: { pageSize, pageNum }}) {
        let nextpageSize = pageSize || state.pageSize;
        let nextpageNum = pageSize || state.pageNum;
        return {
          ...state,
          pageSize: nextpageSize,
          pageNum: nextpageNum
        }
      },

    },
}

从上图可看 定义了初始化state数据  还有各种改变状态的方法 比如setLoad(设置加载) getList(获取列表)setPageInit(设置分页页码)

对应的react组件

// 诗歌列表
import React, { Component } from 'react';
import { Table, Tag, Space } from 'antd';
import { connect } from 'dva';
const namespace = 'poemTable';

const mapStateToProps = (state) => {
  const poemList = state[namespace].data || [];
  return Object.assign({}, state[namespace], {
    poemList
  })
};
const mapDispatchToProps = (dispatch) => {
    return {
        onDidMount: (obj) => {
            obj = obj || {}
            dispatch({
              type: `${namespace}/queryInitPoems`,
              payload: {
                  url: '/api/listpoem',
                  params: Object.assign({}, obj)
              }
            });
        }
    };
};

const columns = [
    {
      title: '标题',
      dataIndex: 'title',
      key: '_id',
    },
    {
      title: '书籍',
      dataIndex: 'book',
      key: 'book',
    },
    {
      title: '作者',
      dataIndex: 'auther',
      key: 'auther',
    },
];
@connect(mapStateToProps, mapDispatchToProps)
export default class poemTablePage extends Component {
    constructor(props) {
        super(props);
        this.state = {
        }
    }
    componentDidMount() {
        this.props.onDidMount({
            pageNum: 1,
            pageSize: 10,
        });
    }
    render() {
        let paginationSet = {
            pageSize: this.props.pageSize,
            current: this.props.pageNum,
            total: this.props.total,
            pageSizeOptions: [10, 20, 50, 100],
            onChange: (page, pageSize) => {
                console.log(page, pageSize);
                this.props.onDidMount({
                    pageNum: page,
                    pageSize: pageSize,
                });
            }
        }
        console.log(paginationSet)
        return (
            <div>
                <Table
                    loading={this.props.loading}
                    dataSource={this.props.poemList} 
                    columns={columns} 
                    rowKey={(record) => record._id}
                    pagination={paginationSet}
                />
            </div>

        )
    }
}

通过mapStateToProps, mapDispatchToProps 方法注入到组件props中,table组件中直接去引用redux state中的数据和方法,这样就实现了 数据和代码的良好拆分。

2、使用hook封装的table函数

// 封装hook插件
import {useEffect, useState, useCallback} from 'react';
import {  postData } from '../util/request'
let defaultTableSet = {
    data: [],
    pageNum: 1,
    pageSize: 10,
    total: 0,
}
export function useTableHook(url, params) {
    const [loading, setLoading] = useState(false)
    const [data, setData] = useState(defaultTableSet);
    const loadData = async (inputparams) => {
        setLoading(true);
        if(inputparams) {
            params = inputparams
        }
        let { pageNum, pageSize } = params;
        let request = await postData(url, params);
        setLoading(false);
        setData(prevState => {
            return {...prevState, ...{
                data: request.data.list || [],
                total: request.data.count,
                pageNum,
                pageSize
            }};
        });
    }
    useEffect(() => {
        loadData()
    }, [])
    return {
        loadData,
        ...data,
        loading
    }
}

和 redux类似的思想, 有默认状态,和改变状态的方法 setData, setLoading, 获取数据函数 loaddata

对应的hook函数组件

// 使用hook方法 加载诗歌列表
import { Table, Tag, Space } from 'antd';
import { useTableHook } from '../hook/tablehook'
const columns = [
    {
      title: '标题',
      dataIndex: 'title',
      key: '_id',
    },
    {
      title: '书籍',
      dataIndex: 'book',
      key: 'book',
    },
    {
      title: '作者',
      dataIndex: 'auther',
      key: 'auther',
    },
];
const poemTableHook = () => {
    const gethookdata = useTableHook('/api/listpoem', {
        pageNum: 1,
        pageSize: 10,
    })
    // let poemList = gethookdata.data;
    let paginationSet = {
        pageSize: gethookdata.pageSize,
        current: gethookdata.pageNum,
        total: gethookdata.total,
        pageSizeOptions: [10, 20, 50, 100],
        onChange: (page, pageSize) => {
            console.log(page, pageSize);
            gethookdata.loadData({
                pageNum: page,
                pageSize: pageSize,
            });
        }
    }
    return (
        <div>
            <Table
                loading={gethookdata.loading}
                dataSource={gethookdata.data} 
                columns={columns} 
                rowKey={(record) => record._id}
                pagination={paginationSet}
            />
        </div>
    )

}
export default poemTableHook

通过useState, useEffect方法 就可以 实现将数据和方法 放到组件中。相比较redux模型,hook方法更简介,直观。

以上就是对两个方法的对比和使用。