👕

【React】文章が長くなる時にcollapseが必要か判定する方法

2024/04/02に公開

概要

入力した文章が長い時に、表示の折りたたみを行うようなcollapseを使用することがあると思います。ただ、入力される文章の長さが分からない場合、短い時はcollapseが不要なケースが出てくると思います。今回は文章の長さによってcollapseの表示判定を行う方法をメモ書きします。

対応方針

Reactでの実装を前提とする場合は、こちらのstackoverflowの回答での実装が良いかなと思いました。基本的な実装としては、refのcurrent.scrollHeightcurrent.clientHeightを比較して、表示の判定を行うという方針となります。

前提

  • 使用したReactのバージョンは18.2.0です。
  • 今回の実装では、UIコンポーネントにshadcn/ui、Tailwindを使用しました。Collapseのコンポーネントはshadcn/uiのCollapsibleを使用しました。

実装サンプル

文章が短い時は、以下のCollapseのボタンを非表示にして、

長い時は以下のようにCollapseのボタンを表示するようにした、実装のサンプルです。

type Props = {
  inputText: string;
};

export const SampleCollapseComponent: FC<Props> = ({ inputText }) => {
  const [isOpenCollapse, setIsOpenCollapse] = useState<boolean>(false);
  const [isDisplayCollapsible, setIsDisplayCollapsible] =
    useState<boolean>(false);
  const contentRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (contentRef && contentRef.current) {
      setIsDisplayCollapsible(
        contentRef.current.scrollHeight > contentRef.current.clientHeight
      );
    }
  }, []);

  return (
    <>
      <Card className="ml-2 mt-2 w-[95%]">
        <CardContent>
          <Collapsible open={isOpenCollapse} onOpenChange={setIsOpenCollapse}>
            {isDisplayCollapsible && (
              <div className="flex flex-row justify-end">
                <CollapsibleTrigger asChild>
                  <Button variant="ghost" size="sm" className="w-9 p-0">
                    <ChevronsUpDown className="h-4 w-4" />
                    <span className="sr-only">Toggle</span>
                  </Button>
                </CollapsibleTrigger>
              </div>
            )}
            <div
              ref={contentRef}
              className={
                !isOpenCollapse
                  ? "whitespace-pre-wrap line-clamp-3 mt-3"
                  : "whitespace-pre-wrap mt-3"
              }
            >
              {inputText}
            </div>
          </Collapsible>
        </CardContent>
      </Card>
    </>
  );
};

Discussion