• 巧用reduce 实现 checkbox 选中勾选联动


    在使用checkbox组件时经常遇到需要关联checkbox选中状态的需求

    例如 A B C 三个checkbox 中,需要选中c时自动勾选上 A B,而取消A时需要取消B C的选中状态

    思路:

    • 添加时,每一项新建一个数组,通过reduce从前到后遍历每一个checkbox的value,数组中添加上上一子项的id
    • 取消时,每一项新建一个数组,通过reduceRight从后到前遍历每一个checkbox的value,数组中添加上下一父项的id
    • 通过两个数组配合checkbox的checked和onChange 即可以实现改效果

    在真实的场景下返回的数据如下

    const mock = [
      {
        canBeSettled: 'yes',
        date: '2020-03-01',
        id: 18,
        settled: 'yes',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
      },
      {
        canBeSettled: 'yes',
        date: '2020-08-01',
        id: 19,
        settled: 'yes',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
      },
      {
        canBeSettled: 'yes',
        date: '2021-03-01',
        id: 20,
        settled: 'no',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
      },
      {
        canBeSettled: 'yes',
        date: '2021-08-01',
        id: 21,
        settled: 'no',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
      },
      {
        canBeSettled: 'yes',
        date: '2022-03-01',
        id: 22,
        settled: 'no',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
      },
      {
        canBeSettled: 'yes',
        date: '2022-08-01',
        id: 23,
        settled: 'no',
        shareAmount: '44835.16',
        tips: '200000.00 x 40% x (153/273) ',
      },
      {
        canBeSettled: 'no',
        date: '2023-03-01',
        id: 24,
        settled: 'no',
        shareAmount: '17875.46',
        tips: '200000.00 x 40% x (153/273) ',
      },
    ]
    

    这时可以用reduce来遍历格式化数据

    const mockFilter = mock
     .reduce((t, v, i, a) => {
       const overToday = moment(v.date).isAfter(new Date(), 'day')
    
       return [
         ...t,
         {
           ...v,
           settledIds:
             v.canBeSettled === 'yes' && !overToday && v.settled === 'no'
               ? [v.id, ...(t[t.length - 1]?.settledIds || [])]
               : [],
         },
       ]
     }, [])
     .reduceRight((t, v, i, a) => {
       const overToday = moment(v.date).isAfter(new Date(), 'day')
       return [
         ...t,
         {
           ...v,
           removeSettledIds:
             v.canBeSettled === 'yes' && !overToday && v.settled === 'no'
               ? [v.id, ...(t[t.length - 1]?.removeSettledIds || [])]
               : [],
         },
       ]
     }, [])
    

    根据场景需求格式化数据,格式化后的数据为:

     [
      {
        canBeSettled: 'yes',
        date: '2020-03-01',
        id: 18,
        settled: 'yes',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [],
        settledIds: []
      },
      {
        canBeSettled: 'yes',
        date: '2020-08-01',
        id: 19,
        settled: 'yes',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [],
        settledIds: []
      },
      {
        canBeSettled: 'yes',
        date: '2021-03-01',
        id: 20,
        settled: 'no',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [20,21,22],
        settledIds: [20]
      },
      {
        canBeSettled: 'yes',
        date: '2021-08-01',
        id: 21,
        settled: 'no',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [21,22],
        settledIds: [20,21]
      },
      {
        canBeSettled: 'yes',
        date: '2022-03-01',
        id: 22,
        settled: 'no',
        shareAmount: '17289.38',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [22],
        settledIds: [20,21,22]
      },
      {
        canBeSettled: 'yes',
        date: '2022-08-01',
        id: 23,
        settled: 'no',
        shareAmount: '44835.16',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [],
        settledIds: []
      },
      {
        canBeSettled: 'no',
        date: '2023-03-01',
        id: 24,
        settled: 'no',
        shareAmount: '17875.46',
        tips: '200000.00 x 40% x (153/273) ',
        removeSettledIds: [],
        settledIds: []
      },
    ]
    

    这样的数据结构可以轻松通过chcekbox的checked属性和onChange熟悉来控制该组件,实现联动的效果

    const [settlementId, setSettlementId] = useState<number[]>([])
    
    return (
    {
       mockFilter.map(value=>{
       <Checkbox
           disabled={value.canBeSettled === 'no' || overToday}
           checked={settlementId.includes(value.id)}
           onChange={(e) => {
              if (e.target.checked) {
                      setSettlementId([...new Set([...settlementId, ...value?.settledIds])])
              } else {
                      setSettlementId(settlementId.filter((item) => !value?.removeSettledIds.includes(item)))
              }
           }}
        />
       })
    }
    
    )
    
  • 相关阅读:
    笑话(真人真事)一则
    Object Builder中的Locator究竟是不是采用Composite的模式之我见
    C++AndC#我的程序员之路
    C#中各种十进制数的转换
    使用GotDotnet workSpace手记
    检索 COM 类工厂中 CLSID 为 {0002450000000000C000000000000046} 的组件失败
    CSS如何让同一行的图片和文字垂直居中对齐(FF,Safari,IE都通过)
    怎样练习一万小时成为顶级高手?
    CSS控制大小写
    做SEO权重计算公式
  • 原文地址:https://www.cnblogs.com/kangxinzhi/p/16423276.html
Copyright © 2020-2023  润新知