UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Web】JavaScriptとReactでつくるWebアプリのデザインパターン

JavaScriptとReactでつくるWebアプリのデザインパターンがまとめられたサイトを知ったのでみてみた

javascriptpatterns.vercel.app

まずは、よくきく以下のようなデザパタをJSでやる方法がめちゃめちゃわかりやすく載っている

  1. モジュールパターン
  2. シングルトンパターン
  3. プロキシパターン
  4. オブサーバーパターン
  5. ファクトリーパターン

ほかにも、Reactでのデザパタ、パフォーマンスパターン、レンダリングパターンなるものが紹介されている

Reactはコンテナー/プレゼンテーションやHOCなど、Hooks時代ではあまり使わないかもという感じだがが参考になった

知らなかったのはReactで行う複合パターンというもの

以下のようなサジェストを出す際に、選択された値とリストを開閉状態と各リストをクリックしたときの挙動を複数のコンポーネントで共有する必要がある

こんなとき複合パターンを使うみたい

例えばFlyOutプロバイダーを作って、そこからInputやListやListItemを提供するようにつくる

const FlyOutContext = React.createContext();

export function FlyOut(props) {
  const [open, setOpen] = React.useState(false);
  const [value, setValue] = React.useState("");
  const toggle = React.useCallback(() => setOpen((state) => !state), []);

  return (
    <FlyOutContext.Provider value={{ open, toggle, value, setValue }}>
      <div>{props.children}</div>
    </FlyOutContext.Provider>
  );
}

function Input(props) {
  const { value, toggle } = React.useContext(FlyOutContext);

  return <input onFocus={toggle} onBlur={toggle} value={value} {...props} />;
}

function List({ children }) {
  const { open } = React.useContext(FlyOutContext);

  return open && <ul>{children}</ul>;
}

function ListItem({ children, value }) {
  const { setValue } = React.useContext(FlyOutContext);

  return <li onMouseDown={() => setValue(value)}>{children}</li>;
}

FlyOut.Input = Input;
FlyOut.List = List;
FlyOut.ListItem = ListItem;

これにより、使う側は状態管理を気にする必要がなくなる

import React from "react";
import { FlyOut } from "./FlyOut";

export default function SearchInput() {
  return (
    <FlyOut>
      <FlyOut.Input placeholder="Enter an address, city, or ZIP code" />
      <FlyOut.List>
        <FlyOut.ListItem value="San Francisco, CA">
          San Francisco, CA
        </FlyOut.ListItem>
        <FlyOut.ListItem value="Seattle, WA">Seattle, WA</FlyOut.ListItem>
        <FlyOut.ListItem value="Austin, TX">Austin, TX</FlyOut.ListItem>
        <FlyOut.ListItem value="Miami, FL">Miami, FL</FlyOut.ListItem>
        <FlyOut.ListItem value="Boulder, CO">Boulder, CO</FlyOut.ListItem>
      </FlyOut.List>
    </FlyOut>
  );
}

他にもパフォーマンスに関するパターンと、レンダリングに関するパターンがあり、知っていたが改めて参考になった