美文网首页
使用 React Component Generator 复用类

使用 React Component Generator 复用类

作者: VioletJack | 来源:发表于2021-01-24 20:51 被阅读0次

用法

当我们项目在开发一类下拉框 Select 组件时,大致逻辑差不多。但是有几点不同:

  • Select 的 Option 项渲染方式不同,有的是文本,有的是标签,有的是带图标的文本……
  • Select 的 Option 数据获取方式不同,各类数据通过不同的 API 来获取。
  • 由于下拉 Option 的数据不同,其筛选方式也不相同。

component generator 简单示例

export const generateSwitch = (name, options) => {
  const propTypes = {
    className: PropTypes.string,
    activeKey: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    onChange: PropTypes.func.isRequired,
  };

  const Switch = (props) => {
    ...
    return (
      <span className={classes}>
        {
          options.map((entry, index) => (
            ...
          ))
        }
      </span>
    );
  };

  Switch.propTypes = propTypes;
  Switch.displayName = name;
  return Switch;
};

export const ASwitch = generateSwitch('ABSwitch', [
  { name: 'AA', key: 'a' },
  { name: 'BB', key: 'b' },
]);

export const BSwitch = generateSwitch('CDSwitch', [
  { name: 'CC', key: 'c' },
  { name: 'DD', key: 'd' },
]);

解决方案

针对最初的问题,我们在项目中使用了 component generator 来实现:

import React, { useState, useEffect, useCallback } from 'react'
import { Select } from 'antd'

export const enumPickerGenerator = (
  // 由于数据格式不同,获取的 select 的 key 和 value 的属性也不同
  keyKey,
  valueKey,
  listGetter,
  renderOption,
  optionFilter
) => {
  return (props) => {
    const { onChange, getPopupContainer, value } = props
    const [listOptions, setListOptions] = useState([])

    useEffect(() => {
      const init = async () => {
        setLoading(true)
        try {
          setListOptions(await listGetter())
        } catch (e) {
          //
        }
        setLoading(false)
      }
      init()
    }, [])

    const emitChange = useCallback(
      (latestValue) => {
        if (onChange) {
          onChange(latestValue)
        }
      },
      [onChange]
    )

    const onSelectChange = useCallback(
      (nextValue) => {
        emitChange(nextValue)
      },
      [emitChange]
    )

    const customOptionFilter = useCallback(
      (input, item) => {
        if (!optionFilter) return true
        return optionFilter(input, item, listOptions)
      },
      [listOptions]
    )

    const renderOptionContent = useCallback(
      (opt) => {
        if (typeof renderOption === 'function') return renderOption(opt)
        if (typeof labelKey === 'string') return opt[labelKey]
        return opt[valueKey]
      },
      [renderOption, labelKey, valueKey]
    )

    return (
      <Select
        value={value}
        allowClear
        onChange={onSelectChange}
        filterOption={customOptionFilter}
        getPopupContainer={getPopupContainer}
        placeholder={`请选择`}
      >
        {listOptions.map(opt => (
          <Select.Option value={opt[valueKey]} key={opt[keyKey || valueKey]}>
            {renderOptionContent(opt)}
          </Select.Option>
        ))}
      </Select>
    )
  }
}

最后

以上都是我从同事的代码那儿学来的,感觉很赞的方法。想想有时候也不一定非得买书看教程。看看手头的项目,学习学习其他小伙伴的代码也是很有收获的~

参考资料

相关文章

网友评论

      本文标题:使用 React Component Generator 复用类

      本文链接:https://www.haomeiwen.com/subject/mhzuzktx.html