封装一个antd的Table操作项中的一个展开与收起通用功能

38 篇文章 1 订阅
9 篇文章 0 订阅
本文介绍了在React中不使用插件和库的两种方法实现组件的展开/收起功能,一种是自定义Hook,另一种是利用第三方库简化代码。这两种方法都涉及useState、useEffect和Hook的使用,适用于处理Table组件中的行展开状态管理。
摘要由CSDN通过智能技术生成

第一种方法,不使用任何插件和库 

import React, { useState, useEffect, SetStateAction, Dispatch } from 'react';  
  
// 定义expandedKeys的类型  
type ExpandedKeysType = Set<string>;  
  
// 自定义Hook:useExpandedKeys  
function useExpandedKeys(initialKeys: ExpandedKeysType): [ExpandedKeysType, (key: string) => void] {  
  const [expandedKeys, setExpandedKeys] = useState(initialKeys);  
  
  // 切换某个key的展开/收起状态  
  const toggleByKey: (key: string) => void = (key) => {  
    setExpandedKeys((prevKeys) => {  
      const newKeys = new Set(prevKeys);  
      if (newKeys.has(key)) {  
        newKeys.delete(key);  
      } else {  
        newKeys.add(key);  
      }  
      return newKeys;  
    });  
  };  
  
  // 使用useEffect来监听expandedKeys的变化  
  useEffect(() => {  
    // 这里可以执行依赖于expandedKeys的操作  
    console.log('Expanded keys have changed:', expandedKeys);  
    // 注意:这里的代码会在每次expandedKeys变化时执行  
  }, [expandedKeys]); // 当expandedKeys变化时,这个effect会重新运行  
  
  return [expandedKeys, toggleByKey];  
}  
  
// 定义Item的类型  
type ItemType = {  
  id: string;  
  name: string;  
};  
  
// 使用自定义Hook的的组件  
function MyComponent() {  
  // 使用自定义Hook,初始值为一个空的Set  
  const [expandedKeys, toggleByKey] = useExpandedKeys(new Set<string>());  
  
  // 假设有一个item列表,我们为每个item渲染一个按钮来切换其展开/收起状态  
  const items: ItemType[] = [  
    { id: 'item1', name: 'Item 1' },  
    { id: 'item2', name: 'Item 2' },  
    // ...其他items  
  ];  
  
  return (  
    <div>  
      {items.map((item) => (  
        <div key={item.id}>  
          <button onClick={() => toggleByKey(item.id)}>  
            {expandedKeys.has(item.id) ? '收起' : '展开'}  
          </button>  
          {expandedKeys.has(item.id) && <div>这里是{item.name}的展开内容</div>}  
        </div>  
      ))}  
    </div>  
  );  
}  
  
export default MyComponent;

第二种方法,和第一种大同小异,只不过写法高级一些,并使用了额外的库和插件

import {useMap,useSet} from '@huse/collection';
import constate from 'constate';
import {Key,useCallback,useState} from 'react';

export function useSetWithToggleAndAllChecked(){
    //存和当前全选状态相反的项的key
    // eg:已全展开时,存的是收起的项的key
    const [set,methods]=useSet<string>();
    const [allChecked,setAllChecked]=useState(false);

    const toggleByKey =useCallback(()=>{
       (key:string)=>{
           if(set.has(key)){
               methods.delete(key);
           }else {
               methods.add(key);
           }
       }
    },
    [set,methods]
    );

    const internalSetAllChecked=useCallback(()=>{
        (shouldAllChecked:boolean)=>{
            methods.clear();
            setAllChecked(shouldAllChecked);
        }
    },
    [set,methods,allChecked]
    );

    const checkIfExpandedByKey=useCallback(()=>{
        (key:string)=>{
            const has =set.has(key);
            if(allChecked){
                return !has;
            }else{
                return has;
            }
        }
    },
    [set,methods,allChecked]
    );

    return {
        set,
        methods:{toggleByKey,setAllChecked,internalSetAllChecked},
        isAllChecked:allChecked,
        checkoutExpandedByKey,
    }
};

export const [
    ExpandedRowProvider,
    useAreAllRowsExpanded,
    useToggleRowsExpanded,
    useToggleRowExpandedByKey,
    useCheckIfExpandedByKey,
]=constate(
    useSetWithToggleAndAllChecked,
    value=>value.isAllChecked,
    value=>value.methods.setAllChecked,
    value=>value.methods.toggleByKey,
    value=>value.checkIfExpandedByKey,
)

 ExpandedRowProvider相当于提供一个conText上下文

//使用时,顶层组件
<ExpandedRowProvider>
</ExpandedRowProvider>
//这个key就是后端返回的Table列表数据的每一项key值,或者是id
const isExpanded = useCheckIfExpandedByKey()(key)
const toggleByKey = useToggleRowExpandedByKey();

<a onClick={()=>toggleByKey(key)}>{isExpanded?'收起':'展开'}</a>

代码一下简洁了好多.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以使用 React Hooks 和 antd 的 Collapse 组件来实现一个带有增减功能的折叠面板。 以下是一个简单的示例代码: ``` import React, { useState } from 'react'; import { Collapse, Button } from 'antd'; const { Panel } = Collapse; function MyCollapse(props) { const [panelKeys, setPanelKeys] = useState([]); const onAddPanel = () => { const newKey = `panel-${panelKeys.length + 1}`; setPanelKeys([...panelKeys, newKey]); }; const onRemovePanel = (key) => { const newPanelKeys = panelKeys.filter((item) => item !== key); setPanelKeys(newPanelKeys); }; return ( <div> <Button type="primary" onClick={onAddPanel}> 新增面板 </Button> <Collapse activeKey={panelKeys}> {panelKeys.map((key) => ( <Panel header={`面板 ${key}`} key={key}> {props.children} <Button type="danger" onClick={() => onRemovePanel(key)}> 删除面板 </Button> </Panel> ))} </Collapse> </div> ); } export default MyCollapse; ``` 在 MyCollapse 组件中,通过 useState Hook 来存储当前展开的面板的 key 值数组 panelKeys。在 onAddPanel 函数中,每次新增面板时,生成一个新的 key 值并添加到 panelKeys 数组中。在 onRemovePanel 函数中,根据传入的 key 值过滤掉需要删除的面板的 key 值,并更新 panelKeys 数组。 在组件中,通过 antd 的 Button 组件来实现新增和删除面板的操作。在 Collapse 组件中,通过 activeKey 属性来设置当前展开的面板的 key 值数组。在循环渲染每个面板时,将需要展开和删除的操作按钮放在 Panel 组件的内部,并根据当前循环到的面板的 key 值来设置 Panel 组件的 header 属性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值