Open6

[Astro] コンポーネント間通信

平田直毅平田直毅

Nano Storesのグローバル値を使って、Reactコンポーネント間通信のしくみを作る。
関連のないコンポーネント間でメソッドが実行できるもの。
Emitterのようなもの。

平田直毅平田直毅

ストアを作る。

store/event.ts
import { atom } from 'nanostores'

const isEventUpdated = atom<number>(0)

// イベントの更新を通知
const notifyEventUpdate = () => {
  isEventUpdated.set(isEventUpdated.get() === 0 ? 1 : 0)
}

export { isEventUpdated, notifyEventUpdate }
平田直毅平田直毅

ストアの値の変更を検知して、メソッドを呼び出す処理は元のコードを少し修正する。
元のままではストアの値が0で初期化されたときも実行されてしまう。

watchState.tsx
import { useEffect, useRef } from 'react'

const useWatch = (value: any, callBack = (previousValue: any, newValue: any) => {}) => {
  const ref = useRef(null)
  useEffect(() => {
    ref.current = value
  }, [])

  useEffect(() => {
    const triggerCallback = async (newValue: any, previousValue: any) => {
      // 初期値設定時はコールバックを実行しない
      if (newValue === previousValue) return

      await callBack(newValue, previousValue)
      ref.current = value
    }
    triggerCallback(value, ref.current)
  }, [value])
}

export default useWatch
平田直毅平田直毅

通知イベントを受信するコンポーネントはこうなる。

CompA.tsx
import useWatch from '@/lib/watchState.tsx'
import { isEventUpdated } from '@/store/event'
import { useStore } from '@nanostores/react'

export default function CompA() {
  // ストアされている値をコンポーネント側でも参照する
  const $isEventUpdated = useStore(isEventUpdated)

  /**
   * 他コンポーネントからの通知で実行
   */
  useWatch($isEventUpdated, () => {
    // 実行したい処理
  })
...
平田直毅平田直毅

送信するコンポーネント側ではただ通知関数を呼び出すだけ。

import { notifyEventUpdate } from '@/store/event'

notifyEventUpdate()