React手动实现简版useFusionTable

291 阅读1分钟

由于公司是老项目,react是老的(16),fusion也是老的(1.25), 不能升级,升级完毕项目都跑不起来,所以自己改造写个简单useFusionTable,看了ant-design推荐有个ahooks里面有useFusionTable,看了下就是返回了tableProps、paginationProps、search,修改代码如下

/* eslint-disable react/react-in-jsx-scope */
import { useState, useEffect } from 'react'
import { store } from '../index'
import { loadingStatus } from '@store/Loading/action'
import StatusOptionsText from '@components/StatusOptionsText'
import TagOptionsText from '@components/TagOptionsText'

export default function useFusionTable (promise, defaultParams = {}, options = { }) {
  const defaultDataSource = options.dataSource || []
  const pageable = typeof options.pageable === 'undefined' ? true : options.pageable
  const pageLoading = typeof options.pageLoading === 'undefined' ? true : options.pageLoading
  const manual = typeof options.manual === 'undefined' ? false : options.manual
  const [params, setParams] = useState(defaultParams)
  const [current, setCurrent] = useState(1)
  const [total, setTotal] = useState(1)
  const [pageSize, setPageSize] = useState(10)
  const [selectedRowKeys, setSelectedRowKeys] = useState([])
  const [dataSource, setDataSource] = useState(defaultDataSource)
  const [loading, setLoading] = useState(false)
  const onRowSelectionChange = (selectedRowKeys, records) => {
    setSelectedRowKeys(selectedRowKeys)
  }
  const submit = (values) => {
    if (pageable) {
      setCurrent(1)
    }
    setParams({ ...values })
  }
  const reset = (values) => {
    if (pageable) {
      setCurrent(1)
      setPageSize(10)
    }
    submit(values)
  }
  const onPageSizeChange = (pageSize) => {
    setPageSize(pageSize)
  }
  const onPageChange = (current) => {
    setCurrent(current)
  }
  const onRenderDefault = v => v || '--'
  const onRenderPrice = v => ('¥' + v / 100) || '0'
  const onRenderTag = (options) => {
    // eslint-disable-next-line react/display-name
    return (value) => <TagOptionsText options={options} value={value} />
  }
  const onRenderAction = (actionFn) => {
    // eslint-disable-next-line react/display-name
    return (value, index, records) => {
      let actionList = []
      actionFn(value, index, records).forEach(action => {
        if (action instanceof Object && !action.$$typeof) {
          Object.keys(action).forEach(val => {
            const newAction = action[val]
            // eslint-disable-next-line eqeqeq
            if (value == val) {
              actionList = [...actionList, ...[].concat(newAction)]
            }
          })
        } else {
          actionList = [...actionList, ...[].concat(action)]
        }
      })
      return <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '16px' }}>
        {actionList}
      </div>
    }
  }
  const onRenderStatus = (options) => {
    // eslint-disable-next-line react/display-name
    return (value) => <StatusOptionsText options={options} value={value} />
  }
  const setLoadingAndDispatch = (loading) => {
    setLoading(loading)
    if (pageLoading) {
      store.dispatch(loadingStatus(loading))
    }
  }
  const run = () => {
    if (!promise || defaultDataSource.length) {
      return
    }
    setLoadingAndDispatch(true)
    const newParams = { ...params }
    if (pageable) {
      newParams.current = current
      newParams.size = pageSize
    }
    promise(newParams).then(res => {
      if (pageable) {
        const data = res.data.data || { records: [], total: 1 }
        setDataSource(data.records)
        setTotal(parseInt(data.total))
      } else {
        const data = res.data.data || []
        setDataSource(data)
      }
    }).finally(() => {
      setLoadingAndDispatch(false)
    })
  }

  useEffect(() => {
    !manual && run()
    // 请求数据
  }, [current, pageSize, params, manual])

  return {
    tableProps: {
      dataSource,
      loading,
      selectedRowKeys,
      onRowSelectionChange,
      onRenderDefault,
      onRenderTag,
      onRenderStatus,
      onRenderAction,
      onRenderPrice
    },
    paginationProps: {
      current,
      pageSize,
      total,
      onPageChange,
      onPageSizeChange
    },
    search: {
      defaultParams,
      params,
      submit,
      reset
    },
    run
  }
}

调用地方修改

function Page() {
  const {
    tableProps: {
      dataSource,
      selectedRowKeys,
      onRowSelectionChange,
      onRenderDefault,
      onRenderTag,
      onRenderStatus,
      onRenderAction
    },
    paginationProps: {
      current,
      total,
      pageSize,
      onPageChange,
      onPageSizeChange
    },
    search: {
      defaultParams,
      submit,
      reset
    },
    run
  } = useFusionTable(apiEmployee.pageList, {
    accountBind: undefined,
    employMobile: undefined,
    employeeStatuses: [],
    fuzzyEmployeeInfo: undefined
  })
  return <div className='enterprise-staff-list'>
    <Search
      itemSource={itemSource}
      values={defaultParams}
      onSearch={submit}
      onReset={reset}
      className='enterprise-staff-list__search'
    />
    <Table
      tableTitle='成员列表'
      dataSource={dataSource}
      total={total}
      pageSize={pageSize}
      current={current}
      cacheSelected={true}
      rowSelection={{
        onChange: onRowSelectionChange,
        selectedRowKeys
      }}
      onPageSizeChange={onPageSizeChange}
      onPageChange={onPageChange}
    >
      <Table.Column align='center' title="表格栏目" dataIndex="id" width={150} cell={onRenderDefault} />
    </RYTable>
  </div>
}

这样有挺多好处的,公用的方法不管同步、异步可以单独抽离