npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-use-table

v1.1.3

Published

react+antd 自定义useTable:轻松处理【搜索、排序、表格、分页】。这个插件能减少你一般列表页50%以上的代码量和维护成本

Downloads

28

Readme

useTable:轻松处理【搜索、排序、表格、分页】

介绍

  1. 本插件基于ReactAnt Design,只能用于React + Antd的列表页
  2. 本插件支持多项自定义配置
  3. 本插件主要用于列表页中的搜索、排序、表格、分页等功能,能处理典型的列表页

image

使用方式

安装

npm i react-use-table

引入

全局配置

// src/hooks/use-table.js
import useTable from 'react-use-table'
import { axios } from '@/common'

export default (params = {}) => {
  return useTable({
    axios: axios, // 自己的axios实例
    url: params.url, // 接口
    queryParams: {// 查询参数
      ...params.queryParams // 实际调用时可以修改全局配置
    },
    customConfig: {// 自定义全局配置
      qsStringify: true,
      showSizeChanger: true,
      totalRowsName: 'total',
      responseCurPageName: 'currentPage',
      ...params.customConfig
    }
  })
}

配置会以一个优先顺序进行合并。这个顺序是:在 lib/bundle.js 找到的库的默认值,然后是实例的 全局 配置,最后是局部配置 。后者将优先于前者

局部调用

import useTable from '@hooks/use-table'
const { dataList, loading, pagination, searchData, setSearchData } = useTable({
  url: '/customer/balance/list.json',
  customConfig: {
    showSizeChanger: true // 这里的showSizeChanger会覆盖全局的showSizeChanger
  }
})

基本使用示例

// index.jsx
import React from 'react'
import { observer } from 'mobx-react-lite'
import SearchForm from './module/SearchForm'
import List from './module/List'
import useTable from '@hooks/use-table.js'

export default observer(() => {
  const { dataList, loading, pagination, searchData, setSearchData } = useTable({
    url: '/customer/balance/list.json',
    queryParams: {
      status: 1 // 配置初始默认查询参数
    },
    customConfig: {
      pageSize: 5
    }
  })
  return (
    <>
      <SearchForm searchData={searchData} setSearchData={setSearchData} />
      <List dataList={dataList} loading={loading} pagination={pagination} searchData={searchData} setSearchData={setSearchData} />
    </>
  )
})

搜索区域

// SearchForm
// 搜索
const handleSearch = (data) => {
	// data为接口入参
  setSearchData(data, { current: 1 })
}

// 重置
const handleClear = () => {
  form.resetFields()
  // 重置的时候不要忘记初始默认查询参数
  setSearchData({ status: 1 }, { current: 1 })
}

列表区域

// List
// useTable内部处理了`loading、dataList、pagination`
<Table
  loading={loading}
  columns={columns}
  dataSource={dataList}
  rowKey='id'
  pagination={pagination}
/>

搜索示例

// SearchForm
// 搜索
const handleSearch = (data) => {
	// data为接口入参,参数二为分页配置,通过设置current,让分页回到第一页,并且接口从第一页开始搜索
  setSearchData(data, { current: 1 })
}

// 重置
const handleClear = () => {
  form.resetFields()
  // 重置的时候不要忘记初始默认查询参数
  setSearchData({ status: 1 }, { current: 1 })
}

// 新增
const add = (data) => {
  add(data).then(() => {
  	// 新增完成后回到首页查看
    setSearchData({}, { current: 1 })
  })
}

// 删除
const deleteRows = (record) => {
  del({ id: record?.id }).then(() => {
  	// setSearchData不传参数,默认为当前的搜索参数和分页参数
    setSearchData()
  })
}

排序示例

单字段排序

import React from 'react'
import { observer } from 'mobx-react-lite'
import { Table, Button } from 'antd'
import useTable from '@hooks/use-table'

export default observer(() => {
  // ①结构出onChange
  const { dataList, loading, pagination, onChange } = useTable({
    url: '/customer/balance/list.json'
  })

  // 客户
  const columns = [
    {
      title: '客户名称',
      dataIndex: 'customerName'
    },
    {
      title: '集团名称',
      dataIndex: 'groupName'
    },
    {
      title: '手机号',
      dataIndex: 'tel',
      align: 'right',
      sorter: true // ②配置排序,单字段排序,排序字段为dataIndex指定值
    },
    {
      title: '更新时间',
      dataIndex: 'lastModifyTime',
      sorter: true // ②配置排序,单字段排序,排序字段为dataIndex指定值
    },
    {
      title: '操作',
      dataIndex: 'customerXbbId',
      className: 'tableopt',
      render() {
        return (
          <Button type='link'>编辑</Button>
        )
      }
    }
  ]
  
  、、、

  return (
    <section className='table-block'>
      <Table
        loading={loading}
        columns={columns}
        dataSource={dataList}
        rowKey='customerXbbId'
        pagination={pagination}
        onChange={onChange} // ③绑定Table onChange事件
      />
    </section>
  )
})

排序入参

多字段排序

const columns = [
  {
    title: '手机号',
    dataIndex: 'tel',
    sorter: {
      multiple: 1 // 值即为当前排序字段权重
    }
  },
  {
    title: '待提现',
    dataIndex: 'availableBalance',
    sorter: {
      multiple: 2 // 值即为当前排序字段权重
    }
  }
]

排序入参

image

切换Tab示例

// 切换tabconst changeTabs = (tabKey) => {  // tab变化只影响入参的一个字段,将searchData作为原参数传入,然后修改该参数值  setSearchData({ ...searchData, status: tabKey }, { current: 1 })}

切换Tab时调用不同接口

// 切换tab,并且处理接口const changeTabs = (tabkey) => {  let url  if (key === 'grabHistory') {    url = '/agent/schedule/grabhistory.json'  } else {    url = '/agent/schedule/joblist.json'  }  setSearchData({ ...searchData, status: tabKey }, { current: 1 }, { url }) // 这里来动态配置当前调用的接口

获取接口返回data数据示例

// responseData即为接口返回的data数据
const { dataList, loading, pagination, searchData, setSearchData, responseData } = useTable({
  url: '/customer/balance/list.json'
})

自定义接口返回数据字段、结构

组件默认的接口返回去数据结构和字段如下

{
  data: {
    curPage: 0,
    dataList: [],
    pageSize: 15,
    totalRows: 56
  },
  flag: 1
}

但是你的接口返回的数据结构和字段比不是这样,组件提供两种方式解决

结构相同,字段不一致

比如你的接口返回数据结构是:

{
  dataObj: {
    currentPage: 0,
    list: [],
    pageSize: 15,
    totalNumber: 56
  },
  code: 200
}

这些字段要改为插件需要的字段,可以通过以下方法配置:

useTable({
    customConfig: {// 自定义全局配置,
      flagKeyName: 'code',
      flagValue: 200,
      responseDataKeyName: 'dataObj',
      responseCurrentPageName: 'currentPage',
      totalRowsKeyName: 'totalNumber',
      listKeyName: 'list'
    }
  })

结构不同

比如你的接口返回数据结构如下,要转换为组件需要的数据结构和字段

{
  code: 200,
  message: 'OK',
  list: [],
  totalNumber: 100,
  current: 1
}

通过responseDataFormat修改

useTable({
  customConfig: {
    responseDataFormat: (resData) => {
      return {
        flag: res.code === 200 ? 1 : 0,
        data: {
          totalRows: res.totalNumber,
          dataList: res.list,
          curPage: res.current
        }
      }
    }
  }
})

同时调用多个useTable示例

const { dataList, loading, pagination, searchData, setSearchData, onChange, responseData } = useTable({
  url: 'userc/getlist.json'
})

// 返回值使用别名就好了😘
const { dataList: dataList2, loading: loading2, pagination: pagination2, pagination: pagination2, setSearchData: setSearchData2, onChange: onChange2, responseData: responseData2 } = useTable({
  url: 'userc/getdetail.json'
})

完整示例

// index.jsx
// ------------------外部资源
import React, { useEffect, useContext } from 'react'
import { observer } from 'mobx-react-lite'
import { Alert } from 'antd'
import useTable from '@hooks/use-table'
import Store from './store'
import SearchForm from './module/SearchForm'
import List from './module/List'

export default observer(() => {
  const store = useContext(Store)

  useEffect(() => {
    return () => {
      store.setStore({
        tabKey: '1'
      })
    }
  }, [])

  const { dataList, loading, pagination, searchData, setSearchData, onChange, responseData } = useTable({
    url: '/userc/assetlist.json',
    queryParams: { tabKey: store.tabKey, status: 1 },
    customConfig: {
      pageSize: 5
    }
  })

  return (
    <>
      <SearchForm searchData={searchData} setSearchData={setSearchData} />

      <Alert style={{ marginBottom: 16 }} message={`巴拉巴拉,这里说一句话:${responseData.totalRows || ''};这里有Tab、时间、职能、排序、跨页选、提示等组件,是一个丰富的常见列表。==你需要把不需要的功能代码删掉==`} type='info' showIcon />

      <List dataList={dataList} loading={loading} pagination={pagination} searchData={searchData} setSearchData={setSearchData} onChange={onChange} />
    </>
  )
})
// SearchForm
import React, { useContext } from 'react'
import { observer } from 'mobx-react-lite'
import { Form, Button, Row, Col, Input, Card, Select } from 'antd'
import Store from '../../store'

export default observer(({ searchData, setSearchData }) => {
  const store = useContext(Store)
  const [form] = Form.useForm()

  // 搜索
  const handleSearch = (data) => {
    const params = {
      ...data,
      tabKey: store.tabKey
    }
    setSearchData(params, { current: 1 })
  }

  // 重置
  const handleClear = () => {
    form.resetFields()

    // 这里重置没有重置排序
    // 如果你要重置时即排序数据也重置页面,列表Column sort请使用变量设置true/false控制
    setSearchData({ tabKey: store.tabKey, status: 1, sortForms: searchData.sortForms }, { current: 1 })
  }

  return (
    <Card className='search-block'>
      <Form form={form} onFinish={handleSearch} initialValues={{ status: 1 }}>
        <Row gutter={24}>
          <Col span={4}>
            <Form.Item name='jobKeyword'>
              <Input placeholder='职位ID/职位名' allowClear />
            </Form.Item>
          </Col>
          <Col span={4}>
            <Form.Item name='brandName'>
              <Input placeholder='品牌' allowClear />
            </Form.Item>
          </Col>
          <Col span={4}>
            <Form.Item name='expireTime'>
              <Input placeholder='姓名' allowClear />
            </Form.Item>
          </Col>
          <Col span={4}>
            <Form.Item name='serviceType'>
              <Input placeholder='年龄' allowClear />
            </Form.Item>
          </Col>
          <Col span={4}>
            <Form.Item name='status'>
              <Select placeholder='状态' allowClear>
                <Select.Option value={1}>状态1</Select.Option>
                <Select.Option value={2}>状态2</Select.Option>
                <Select.Option value={3}>状态3</Select.Option>
              </Select>
            </Form.Item>
          </Col>
          <Col span={4}>
            <Form.Item className='actions'>
              <Button type='primary' htmlType='submit' style={{ marginRight: 20 }}>
                搜索
              </Button>
              <Button onClick={handleClear}>
                重置
              </Button>
            </Form.Item>
          </Col>
        </Row>
      </Form>
    </Card>
  )
})
// List
import React, { useContext } from 'react'
import { observer } from 'mobx-react-lite'
import { Table, Tabs, Button } from 'antd'
import Store from '../../store'

export default observer(({ dataList, loading, pagination, searchData, setSearchData, onChange }) => {
  const store = useContext(Store)

  // 切换tab
  const changeTabs = (tabKey) => {
    setSearchData({ ...searchData, tabKey }, {
      current: 1
    })
  }

  // 新增
  const add = () => {
    setTimeout(() => {
      setSearchData({}, { current: 1 })
    })
  }

  // 编辑
  const edit = (record) => {
    setTimeout(() => {
      setSearchData()
    })
  }

  const columns = [
    {
      title: 'ID',
      dataIndex: 'userXhCId',
      filterKey: 'userXhCId'
    },
    {
      title: '手机号',
      dataIndex: 'tel',
      sorter: true,
      render() {
        return Math.random()
      }
    },
    {
      title: '待提现',
      dataIndex: 'availableBalance',
      sorter: true // 设置为变量可以用来开启/关闭排序(用于重置)
    },
    {
      title: '累计完成人次',
      dataIndex: 'totalFinishServiceCnt'
    },
    {
      title: '累计收入',
      dataIndex: 'totalIncome'
    },
    {
      title: '操作',
      dataIndex: 'userXhCId',
      className: 'tableopt',
      width: 120,
      render(text, record) {
        return (
          <>
            <Button size='small' type='link' onClick={() => edit(record)}>编辑</Button>
            <Button size='small' type='link' danger>删除</Button>
          </>
        )
      }
    }
  ]

  return (
    <section className='table-block'>
      <Tabs
        animated={false}
        activeKey={store.tabKey}
        onChange={changeTabs}
        tabBarExtraContent={<div className='top-btn-group'>
          <Button type='primary' onClick={add}>新增职位</Button>
        </div>}
      >
        <Tabs.TabPane tab='运行中' key='1' />
        <Tabs.TabPane tab='全部职位' key='2' />
      </Tabs>

      <Table
        loading={loading}
        columns={columns}
        dataSource={dataList}
        rowKey='userXhCId'
        pagination={pagination}
        onChange={onChange}
      />
    </section>
  )
})

API

入参 Object

Object Keys

| 属性 | 说明 | 默认值 | 类型 | 版本 | | :----------- | :------------------ | ------ | :------- | ----- | | url | 接口,必填 | | String | | | axios | axios实例,必填 | | Function | | | method | 请求方式 | POST | String | 1.1.0 | | queryParams | 默认请求参数 | | Object | | | customConfig | 自定义配置 | | Object | |

自定义配置customConfig

| 属性 | 说明 | 类型 | 默认值 | | | :------------------ | :----------------------------------------------------------- | ----------------------- | :------------------------------------------------ | ----- | | qsStringify | 是否使用qs模块序列化参数 | Boolean | false | | | pageSizeName | 自定义每页搜索数量key | String | pageSize | | | curPageName | 自定义搜索第几页key | String | curPage | | | pageSize | 自定义每页搜索数量value | Number | 15 | | | showQuickJumper | 是否可以快速跳转至某页 | Boolean | true | | | showSizeChanger | 是否展示 pageSize 切换器 | Boolean | false | | | showTotal | 是否显示数据总量 | Boolean|Function | 共{total}条 | 1.1.0 | | startSearchIndex | 自定义接口搜索起始索引 | Number | 0 | | | flagName | 自定义接口出参-判断接口返回结果成功与失败标识key | String | flag | | | flagValue | 自定义接口出参-判断接口返回结果成功与失败标识value | Number|String|Boolean | 1 | | | dataListName | 自定义接口出参-列表数据key | String | dataList | | | totalRowsName | 自定义接口出参-总条数 | String | totalRows | | | responseCurPageName | 自定义接口出参-当前页key | String | 自定义出参当前页key,默认取curPageName值 | | | responseDataName | 自定义接口出参-data key | String | data | | | sortFormsName | 自定义排序接口入参key | String | sortForms | | | sortFiledName | 自定义排序字段key | String | sortFiled | | | sortTypeName | 自定义排序 order by key | String | sortType | | | weightName | 自定义排序权重key | String | weight | | | axiosConfig | 自定义axios请求配置 | Object | {} | | | responseDataFormat | 修改接口返回数据 | Function | | 1.0.0 |

出参

| 属性 | 说明 | 类型 | 版本 | | :------------ | :----------------------------------------------------------- | :----------------------------------------------------------- | ----- | | dataList | 列表数据 | Array | | | setDataList | 修改列表数据 | Function(Array) | | | pagination | Pagination分页组件配置 | Object | | | loading | loading | Boolean | | | setLoading | 修改loading | Function(Boolean) | | | searchData | 接口查询参数 | Object | | | setSearchData | 修改接口查询参数并搜索 | Function参数1:查询参数[Object]参数2:分页组件参数[Object]参数3:其他参数配置[Object],目前只有url,用于切换tabs时调用不同接口注意:不传参数默认按照当前搜索条件查询 | | | responseData | 接口响应数据data | Object | | | tableProps | 可直接解构在Antd Table组件 | Object: { dataSource, loading, pagination, onChange } | 1.1.0 | | onChange | 绑定Table的onChange函数,本插件v0.1.2用于排序 | Function | |