📡react-call という
ライブラリがアツい!!!

@yKicchan

📡react-call というライブラリがアツい!!!

自己紹介

きっちゃそ
:DeNA
Web Frontend
X @yKicchan
📡react-call というライブラリがアツい!!!

zenn

📡react-call というライブラリがアツい!!!

目次

  1. react-call とは
  2. react-call の使い方
  3. いいところ
  4. まとめ

1. react-call とは

1. react-call とは

demo

1. react-call とは

ReactComponent を
手続き的に呼び出せる

1. react-call とは

手続き的に呼び出せる?

  • 別のコンポーネントから呼び出したり(≒表示したり)
  • その結果を受け取って処理したり
  • Modal や Confirm などの要件にマッチする
1. react-call とは

window.confirm との比較

const message = 'Sure?'
const yes = window.confirm(message)

if (yes) thanosSnap() // 🫰
const props = { message: 'Sure?' }
const yes = await Confirm.call(props)

if (yes) thanosSnap() // 🫰

2. react-call の使い方

2. react-call の使い方

コンポーネントを定義

import { createCallable } from 'react-call'

interface Props { message: string }
type Response = boolean

export const Confirm = createCallable<Props, Response>(
  ({ call, message }) => (
    <div role="dialog">
      <p>{message}</p>
      <button onClick={() => call.end(true)}>Yes</button>
      <button onClick={() => call.end(false)}>No</button>
    </div>
  )
)

createCallable で wrap する

call オブジェクトが props に追加される

call.end(response) で結果を返す

2. react-call の使い方

Root の配置

import { Confirm } from './path/to/Confirm';

export const App = () => (
  <>
    <Confirm.Root />
    {/* 略 */}
  </>
)

createCallable により Root が追加されるので使う

RootConfirm に対して一つだけ配置する

配置場所は最上位である必要はない

2. react-call の使い方

call する 🤙

import { Confirm } from './path/to/Confirm';

export const Anywhere = () => {
  const onClick = async () => {
    const res = await Confirm.call({ message: 'Sure?' });
    if (res) thanosSnap();
  }
  
  return <button onClick={onClick}>Snap</button>
}

利用したい場所で call するだけ✨

配置した Root 以下の必要がある

3. いいところ

3. いいところ

表示の状態管理が不要

const [open, setOpen] = useState(false);

return (
  <>
    <Button onClick={() => setOpen(true)}>open</Button>
    <Modal open={open} onClose={() => setOpen(false)}>
      <!-- 略 -->
    </Modal>
  </>
);

こういう useState が不要になり責務がスッキリする

3. いいところ

呼び出し側からも更新/終了できる

const promise = Alert.call({ message: 'Starting operation...' })

await asyncOperation()

Alert.update(promise, { message: 'Completed!' })
setTimeout(() => Alert.end(promise), 3000)

promise を渡して特定の呼び出しに対して更新/終了できる

3. いいところ

呼び出し側からも更新/終了できる

// すべての Confirm を終了させる
Confirm.end(false)

// すべての Alert を更新する
Alert.update({ message: 'Completed!' })

一度に呼び出す数が一つだけの場合もこの方がスッキリする

3. いいところ

ネストもできる

interface Props { i: number; }

export const Modal = createCallable<Props>(
  ({ call, i }) => (
    <div role="dialog">
      <p>{i}個目のモーダル</p>
      <button onClick={() => Modal.call({ i: i + 1 })}>Call {i + 1}</button>
      <button onClick={() => call.end()}>Close</button>
    </div>
  )
);

ネスト結果の取り回しは実装が必要

3. いいところ

終了アニメーションに対応できる

const UNMOUNTING_DELAY = 500

export const Modal = createCallable(
  ({ call }) => (
    <div className={clsx({
      'exit-animation': call.ended,
    })}>
      {/* 略 */}
    </div>
  ),
  UNMOUNTING_DELAY
)
.exit-animation {
  opacity: 0;
  transition: opacity .5s;
}

createCallable の第二引数で unmount までの時間を指定

call.ended で終了判定ができる

3. いいところ

サポート環境

  • ✅ TypeScript
  • ✅ ReactNative
  • ✅ SSR (セットアップ)

react-domWebAPI に依存していないため動作環境を選ばない

3. いいところ

SSR 注意点

<Confirm.Root />

Root の設置(セットアップ)は SSR に対応

const response = await Confirm.call();

call はクライアントサイドのみで利用可能

4. まとめ

4. まとめ

まとめ

  • react-call手続き的にコンポーネントを呼び出せる
  • Promise を利用したシンプルな IF で簡単に利用できる
  • 外からの更新/終了終了アニメーション等のユースケースにも対応可能
4. まとめ

もう少し詳しい情報

zenn

EOF