A scene that uses render props instead of hooks

Posted May 28, 20202 min read

Custom column function

Requirements

There are too many columns in the table, you need to implement a custom column function.
This custom column may be used in multiple places, so I want to make it universal

Thinking and Realizing

Then the first consideration is that hooks, hooks can manage columns, and finally output a filtered(customized) column, and the component renders according to this column.

But there is a problem. The UI for filtering may also be made universal. Isn't it silly to call the UI for filtering by each parent component.

So in the face of this reuse of both UI and logical reuse, hooks is difficult to handle, or use render props to deal with it.

The following is a simple custom column component implemented.

/*
* @File:custom table column
* @Author:nsne
* @Date:2020-01-03 15:08:32
* @Last Modified by:nsne
* @Last Modified time:2020-01-03 17:16:30
* @Usage
*

{(columns:ColumnProps []) =>(
<Table
className = {${styles.mTaskTable} ${className}}
expandRowByClick
expandedRowKeys = {expandedRowKeys}
onExpandedRowsChange = {onExpandedRowsChange}
{... restProps}
columns = {columns}
/>
)}

*
* /
import React, {useState, useEffect} from 'react';
import {Popover, Button, Checkbox} from 'antd';
import {ColumnProps} from 'antd/lib/table';
import _ from 'lodash';
import styles from './index.less';

const CustomColumn =(props:{
  columns:ColumnProps <any> [];
  defaultColumns ?:Array <ColumnProps <any> | string>;
  children:(columns) => React.ReactNode;
}) => {
  const {columns = []} = props;
  const [column, setColumn]= useState(columns);
  const onChange = value => {
    const {columns = []} = props;
    const column = columns.filter(
      item => value.includes(item.dataIndex) || value.includes(item.title),
   );
    setColumn(column);
  };

  let {defaultColumns = []} = props;
  useEffect(() => {
    defaultColumns = defaultColumns? .length? defaultColumns:columns;
    const defaultValue = defaultColumns
      .map(item =>(typeof item === 'string'? item:item? .dataIndex || _.toString(item? .title)))
      .filter(item => column.some(cell => cell.dataIndex === item || cell.title === item));
    onChange(defaultValue);
  }, []);

  const renderContent =() =>(
    <Checkbox.Group
      options = {columns? .map((item:ColumnProps <any>, index) =>({
        label:item.title || '',
        value:item.dataIndex || _.toString(item.title) || index,
      }))}
      value = {column.map(item => item.dataIndex || _.toString(item.title))}
      onChange = {onChange}
    />
 );

  return(
    <div className = {styles.cCustomColumn}>
      <Popover
        content = {renderContent()}
        title = "Please select the column name to be displayed"
        trigger = "click"
        overlayClassName = {styles.mCustomPopover}
      >
        <Button icon = "setting"> Custom column </Button>
      </Popover>
      {props.children(column)}
    </div>
 );
};

export default CustomColumn;