shadcn-ahooks

useSelections

This hook is used for Checkbox group, supports multiple selection, single selection, select-all, select-none and semi-selected etc.

Overview

This hook is used for Checkbox group, supports multiple selection, single selection, select-all, select-none and semi-selected etc.

Documentation and Examples

Installation

Open in
pnpm dlx shadcn@latest add https://shadcn-ahooks.vercel.app/r/useSelections.json
npx shadcn@latest add https://shadcn-ahooks.vercel.app/r/useSelections.json
yarn shadcn@latest add https://shadcn-ahooks.vercel.app/r/useSelections.json
bun shadcn@latest add https://shadcn-ahooks.vercel.app/r/useSelections.json

This hook is used for Checkbox group, supports multiple selection, single selection, select-all, select-none and semi-selected etc.

Examples

Default usage

import { Checkbox, Col, Row } from 'antd';
import React, { useMemo, useState } from 'react';
import useSelections from '@/src/hooks/ahooks/useSelections';

export default () => {
  const [hideOdd, setHideOdd] = useState(false);
  const list = useMemo(() => {
    if (hideOdd) {
      return [2, 4, 6, 8];
    }
    return [1, 2, 3, 4, 5, 6, 7, 8];
  }, [hideOdd]);

  const { selected, allSelected, isSelected, toggle, toggleAll, partiallySelected } = useSelections(
    list,
    {
      defaultSelected: [1],
    },
  );

  return (
    <div>
      <div>Selected: {selected.join(',')}</div>
      <div style={{ borderBottom: '1px solid #E9E9E9', padding: '10px 0' }}>
        <Checkbox checked={allSelected} onClick={toggleAll} indeterminate={partiallySelected}>
          Check all
        </Checkbox>
        <Checkbox checked={hideOdd} onClick={() => setHideOdd((v) => !v)}>
          Hide Odd
        </Checkbox>
      </div>
      <Row style={{ padding: '10px 0' }}>
        {list.map((o) => (
          <Col span={12} key={o}>
            <Checkbox checked={isSelected(o)} onClick={() => toggle(o)}>
              {o}
            </Checkbox>
          </Col>
        ))}
      </Row>
    </div>
  );
};

Object array

import { Checkbox, Col, Row } from 'antd';
import React, { useMemo, useState } from 'react';
import useSelections from '@/src/hooks/ahooks/useSelections';

export default () => {
  const [hideOdd, setHideOdd] = useState(false);
  const list = useMemo(() => {
    if (hideOdd) {
      return [2, 4, 6, 8].map((id) => ({ id }));
    }
    return [1, 2, 3, 4, 5, 6, 7, 8].map((id) => ({ id }));
  }, [hideOdd]);

  const { selected, allSelected, isSelected, toggle, toggleAll, partiallySelected } = useSelections(
    list,
    {
      defaultSelected: [{ id: 1 }],
      itemKey: 'id',
    },
  );

  return (
    <div>
      <div>Selected: {JSON.stringify(selected)}</div>
      <div style={{ borderBottom: '1px solid #E9E9E9', padding: '10px 0' }}>
        <Checkbox checked={allSelected} onClick={toggleAll} indeterminate={partiallySelected}>
          Check all
        </Checkbox>
        <Checkbox checked={hideOdd} onClick={() => setHideOdd((v) => !v)}>
          Hide Odd
        </Checkbox>
      </div>
      <Row style={{ padding: '10px 0' }}>
        {list.map((item) => (
          <Col span={12} key={item.id}>
            <Checkbox checked={isSelected(item)} onClick={() => toggle(item)}>
              {item.id}
            </Checkbox>
          </Col>
        ))}
      </Row>
    </div>
  );
};

Pagination

import { Checkbox, Divider, Pagination, Spin } from 'antd';
import React, { useEffect, useState } from 'react';
import useSelections from '@/src/hooks/ahooks/useSelections';

interface DataType {
  id: number;
  title: string;
}

interface PaginationType {
  current: number;
  pageSize: number;
  total?: number;
}

const dataSource = Array.from({ length: 50 }, (item, index) => ({
  id: index,
  title: `title ${index}`,
}));

const getDataFromServer = (props: PaginationType) => {
  const { current, pageSize } = props;
  const data = dataSource.slice((current - 1) * pageSize, current * pageSize);

  return new Promise<{
    data: DataType[];
    total: PaginationType['total'];
  }>((resolve) => {
    setTimeout(
      () =>
        resolve({
          data,
          total: dataSource.length,
        }),
      500,
    );
  });
};

export default () => {
  const [dataList, setDataList] = useState<DataType[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [pagination, setPagination] = useState<PaginationType>({
    current: 1,
    pageSize: 10,
    total: 0,
  });

  const getData = async (params: PaginationType) => {
    setLoading(true);

    const { data, total } = await getDataFromServer(params);

    setLoading(false);
    setDataList(data);
    setPagination({ ...params, total });
  };

  useEffect(() => {
    getData(pagination);
  }, []);

  const { selected, allSelected, isSelected, toggle, toggleAll, partiallySelected } = useSelections(
    dataList,
    {
      itemKey: 'id',
    },
  );

  return (
    <Spin spinning={loading}>
      {dataList.map((item) => {
        const { id, title } = item;

        return (
          <div key={id} style={{ display: 'flex', flexDirection: 'row' }}>
            <Checkbox
              style={{ padding: '4px 8px' }}
              onClick={() => toggle(item)}
              checked={isSelected(item)}
            >
              {title}
            </Checkbox>
          </div>
        );
      })}
      <Pagination
        style={{ margin: '12px 0 16px 0' }}
        size="small"
        showSizeChanger
        current={pagination.current}
        pageSize={pagination.pageSize}
        total={pagination.total}
        onChange={(page, size) => {
          getData({
            current: page,
            pageSize: size,
          });
        }}
      />
      <div
        style={{
          display: 'flex',
          flexDirection: 'row',
          alignItems: 'center',
          paddingLeft: '8px',
        }}
      >
        <Checkbox checked={allSelected} indeterminate={partiallySelected} onClick={toggleAll}>
          Check all
        </Checkbox>
        <span style={{ marginLeft: '90px' }}>Selected: {selected.length}</span>
      </div>
      {!!selected.length && (
        <>
          <Divider />
          {JSON.stringify(selected)}
        </>
      )}
    </Spin>
  );
};

API

interface Options<T> {
  defaultSelected?: T[];
  itemKey?: string | ((item: T) => Key);
}

// works when >=3.8.0, recommended ✅
const result: Result = useSelections<T>(items: T[], options?: Options<T>);

// works when <4.0.0, will be removed in ahooks 4.0 🙅🏻‍♀️
const result: Result = useSelections<T>(items: T[], defaultSelected?: T[]);

Params

PropertyDescriptionTypeDefault
itemsData itemsT[]-
optionsOptional configurationOptions-

Options

PropertyDescriptionTypeDefault
defaultSelectedDefault selected dataT[][]
itemKeyThe unique key of data item. Typically, this parameter needs to be specified when the data source is an array of objectstring | (item: T) => React.Key-

Result

PropertyDescriptionType
selectedSelected itemsT[]
allSelectedIs all items selectedboolean
noneSelectedIs no item selectedboolean
partiallySelectedIs partially items selectedboolean
isSelectedWhether item is selected(value: T) => boolean
setSelectedSelect multiple items. When executed multiple times, the later return value overwrites the previous one, so if you want to merge the results of multiple operations, you need to do this manually: setSelected((oldArray) => oldArray.concat(newArray))(value: T[]) => void | (value: (prevState: T[]) => T[]) => void
selectSelect single item(value: T) => void
unSelectUnSelect single item(value: T) => void
toggleToggle single item select status(value: T) => void
selectAllSelect all items() => void
unSelectAllUnSelect all items() => void
toggleAllToggle select all items() => void
clearAllClear all selected (In general, clearAll is equivalent to unSelectAll. If the items is dynamic, clearAll will clear "all selected data", while unSelectAll will only clear "the currently selected data in the items")() => void

On this page