---
title: "Chip lọc React trong thanh cuộn"
description: "Thanh chip lọc ngang trong React: chip cuộn theo cách gốc, thêm một chip sẽ cuộn nó vào tầm nhìn, kéo để cuộn mà không phá vỡ click. Demo trực tiếp và mã nguồn."
canonical: "https://react-horizontal-scrolling-menu.dev/vi/filter-chips"
image: "https://react-horizontal-scrolling-menu.dev/og.png"
---

# Một thanh chip lọc có thể cuộn, trong React

Dải chip bên dưới mọi thanh tìm kiếm — chủ đề YouTube, bộ lọc cửa hàng, bộ chọn tag — là một vùng chứa cuộn một dòng đầy các nút bật/tắt. 10% khó là những gì xảy ra ở các cạnh: chip mới xuất hiện ngoài màn hình, thao tác kéo không được bật/tắt bất cứ thứ gì, và mũi tên biết khi nào chúng vô nghĩa.

react

typescript

scrolling

menu

gallery

tabs

carousel

slider

accordion

lightbox

Add filter

Thêm một bộ lọc — dải sẽ tự cuộn chip mới vào tầm nhìn.

[Chỉnh sửa ví dụ này trực tiếp trong Storybook](https://asmyshlyaev177.github.io/react-horizontal-scrolling-menu/?path=/story/examples-additemandscrolltoit--add-item-and-scroll-to-it)

## Trường hợp biên chính là tính năng

Bất kỳ dải flex nào với `overflow-x: auto` đều cuộn được. Một thanh chip chứng minh giá trị của nó ở các chi tiết:

-   **Một chip được thêm ngoài màn hình phải tự thông báo.** Demo cuộn đến mỗi chip mới bằng `apiRef.current.scrollToItem(el, 'smooth', 'end')` sau khi render — [ví dụ thêm item và cuộn đến nó](https://react-horizontal-scrolling-menu.dev/vi/examples/add-item-and-scroll-to-it.md) chính là cách nối này.
-   **Kéo để cuộn, click để bật/tắt — không bao giờ cả hai.** Người dùng desktop kéo dải như một bề mặt cảm ứng; thả trên một chip không được lật trạng thái nó. [Công thức kéo](https://react-horizontal-scrolling-menu.dev/vi/examples/mouse-drag.md) theo dõi cử chỉ và ngăn chính cú click đó.
-   **Mũi tên chỉ khi hữu ích.** `useLeftArrowVisible` / `useRightArrowVisible` được nối vào cùng một IntersectionObserver như mọi thứ khác, vì vậy mũi tên bị vô hiệu hóa ở các cạnh thật — kể cả sau khi chip được thêm hoặc xóa.

## Trạng thái vẫn nằm trong tay bạn

Thư viện chỉ cuộn; nó không sở hữu lựa chọn. Chip là các nút của bạn — `aria-pressed` cho các nút bật/tắt đa lựa chọn, state thuần cho đơn lựa chọn — và menu chỉ cần mỗi chip mang một `itemId`. Điều đó nghĩa là trạng thái chip kết hợp được với bất cứ thứ gì bạn đã có: URL search params, một thư viện form, một mô hình lọc do server điều khiển. Xóa một chip là [xóa một item](https://react-horizontal-scrolling-menu.dev/vi/examples/add-items.md); tạo hiệu ứng biến mất là [ví dụ hoạt ảnh item](https://react-horizontal-scrolling-menu.dev/vi/examples/items-animation.md).

## Di động: một cảnh báo về cuộn body

Trên màn hình cảm ứng, một thao tác vuốt ngang bên trong thanh có thể kéo cả trang theo hướng ngang trên một số trình duyệt. Nếu bạn gặp điều đó, [ví dụ ngăn cuộn body](https://react-horizontal-scrolling-menu.dev/vi/examples/prevent-body-scroll.md) trình bày `touch-action` và overscroll containment để khóa nó lại — chỉ dùng CSS, không cần thư viện cử chỉ.

## Mẫu hình, tối giản

Chip là các nút bật/tắt với `itemId`; một ref đến menu API sẽ cuộn chip vừa thêm vào tầm nhìn.

ChipBar.tsx

```
function ChipBar({ options }: { options: string[] }) {
  const apiRef = React.useRef<publicApiType>(null);
  const [selected, setSelected] = React.useState<string[]>([]);

  const toggle = (id: string) =>
    setSelected((cur) =>
      cur.includes(id) ? cur.filter((c) => c !== id) : [...cur, id],
    );

  // A chip appended off-screen scrolls itself into view.
  const addChip = (id: string) => {
    toggle(id);
    requestAnimationFrame(() => {
      const el = apiRef.current?.getItemElementById(id);
      if (el) apiRef.current?.scrollToItem(el, 'smooth', 'end');
    });
  };

  return (
    <ScrollMenu apiRef={apiRef}>
      {options.map((id) => (
        <Chip itemId={id} key={id} pressed={selected.includes(id)}
          onToggle={() => toggle(id)} />
      ))}
    </ScrollMenu>
  );
}
```

## Hoặc cài đặt nó như một component shadcn

Registry item [chip-bar](https://react-horizontal-scrolling-menu.dev/r/chip-bar.json) cung cấp cái này như một controlled component — `options`, `selected`, `onSelectedChange` — được style bằng Tailwind trong `components/ui/` của bạn:

shadcn

```
npx shadcn@latest add https://react-horizontal-scrolling-menu.dev/r/chip-bar.json
```

## Các ví dụ liên quan

-   [Thêm một mục và cuộn đến nóPattern chip bộ lọc: thêm vào, rồi đưa vào view.](https://react-horizontal-scrolling-menu.dev/vi/examples/add-item-and-scroll-to-it.md)
-   [Tải thêm khi thấy điểm cuốiThêm vô hạn chạy theo khả năng hiển thị của mục cuối.](https://react-horizontal-scrolling-menu.dev/vi/examples/add-items.md)
-   [Ngăn cuộn bodyCon lăn trên menu cuộn menu, không phải trang.](https://react-horizontal-scrolling-menu.dev/vi/examples/prevent-body-scroll.md)

[Tất cả 21 ví dụ](https://react-horizontal-scrolling-menu.dev/vi/examples.md)

---

More examples: <https://react-horizontal-scrolling-menu.dev/examples.md>
Library summary for LLMs: <https://react-horizontal-scrolling-menu.dev/llms.txt>
