Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

onUnmountedはonMountedのなかで呼ぶとスッキリしやすい

vueのcomposition APIはどこで呼んでも問題ありません。たとえばonMountedのなかでonUnmountedを呼んでも良いです。

onMounted(() => {
  const handler = () => {};
  window.addEventHandler('event', handler);
  onUnmounted(() => {
    window.addEventHandler('event', handler);
  });
});

onMountedのときに使ったもの(handlerとか)をそのまま流用してonUnmountedを設定できるので、このパターンはかなり有用です。ぜひ使ってみてください。

spread演算子を使うときに {} と {foo:undefined} は挙動が異なる

const obj1 = {
  foo: 42,
  ...({ foo: undefined }),
}; // {foo: undefined}


const obj2 = {
  foo: 42,
  ...({}),
}; // {foo: 42}

↑こんな感じで、undefinedが指定されているときとプロパティ自体がないときでは動作が異なります。

(実は上のコードはそのままだとfooが二重で定義されているとTSに怒られるので、実際に問題になるケースは少ないです)

問題になるケース

const props: {style: CSSProperties} = {
  style: {
    background: cond ? 'blue' : undefined,
  },
};
const style = {
  background: 'red',
  ...props.style,
};

このとき、condがfalseだとbackgroundは'red'ではなくundefinedになってしまいます。

これを解消するために、condがfalseのときにbackgroundを追加しないようにします。

const props = {
  style: {
    ...(cond && {background: 'blue'}),
  },
};
const style = {
  background: 'red',
  ...props.style,
};

これであれば意図した通りに動きます。

Reactで<dialog>いじってみたけどつらい件2

www.pandanoir.info

5年経ったので書き直しをば

interface Props {
  isOpen: boolean;
  onClose: () => void;
}

const Dialog = ({ isOpen, onClose }: Props) => {
  const dialogRef = useRef<HTMLDialogElement>(null);
  useEffect(() => {
    if (isOpen) {
      dialogRef.current?.showModal();
    } else {
      dialogRef.current?.close();
    }
  }, [isOpen]);

  return (
    <dialog ref={dialogRef}>
      <form method="dialog">
        name: <input type="text" />
        <br />
        age: <input type="number" />
        <br />
        <button onClick={onClose}>Cancel</button>
        <button>Confirm</button>
      </form>
    </dialog>
  );
};