ホームページ >ウェブフロントエンド >jsチュートリアル >タイムアウトを指定して Redux アクションをディスパッチするにはどうすればよいですか?

タイムアウトを指定して Redux アクションをディスパッチするにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-27 07:57:13673ブラウズ

How to Dispatch a Redux Action with a Timeout?

タイムアウト付きで Redux アクションを送信するにはどうすればよいですか?

問題:

タイムアウト メカニズムを使用してアプリの通知ステータスを更新する必要があります。通知は通常、エラーまたはメッセージです。通知が表示されないように、5 秒後に別のアクションを送信して通知状態を初期状態に戻す必要があります。主な理由は、通知が 5 秒後に自動的に消える機能を提供するためです。

setTimeout を使用して別のアクションを返そうとしましたが、成功せず、関連するメソッドがオンラインで見つかりませんでした。あらゆる提案を試してみたいと思います。

答え:

すべての操作を関数ライブラリに記述する習慣に限定される必要はありません。 JavaScript でタイムアウトを使用したい場合は、setTimeout を使用してください。同じ原則が Redux アクションにも当てはまります。

Redux で非同期イベントを処理するための代替手段を提供しますが、コードの重複が多すぎることが判明した場合にのみこれらを使用する必要があります。このような問題が発生しない限り、言語が提供するオプションを使用して、最も単純な解決策を追求してください。

非同期コードをインラインで記述する

これが最も簡単な方法です。ここでは Redux 固有のメソッドは使用されません。

store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

同じ操作が接続コンポーネントでも実行されます:

this.props.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  this.props.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

唯一の違いは、ストア自体は通常、接続コンポーネントではアクセスできず、注入によって取得されることです。 dispatch() または特定のアクション作成者への小道具。しかし、私たちにとって、それは何の違いもありません。

異なるコンポーネントで同じアクションを送信するときにタイプミスをしたくない場合は、アクション オブジェクトをインラインで送信する代わりに、アクション作成者を抽出できます。

// actions.js
export function showNotification(text) {
  return { type: 'SHOW_NOTIFICATION', text }
}
export function hideNotification() {
  return { type: 'HIDE_NOTIFICATION' }
}

// component.js
import { showNotification, hideNotification } from '../actions'

this.props.dispatch(showNotification('You just logged in.'))
setTimeout(() => {
  this.props.dispatch(hideNotification())
}, 5000)

または、これらは connect() 経由でバインドされています:

this.props.showNotification('You just logged in.')
setTimeout(() => {
  this.props.hideNotification()
}, 5000)

これまでのところ、ミドルウェアやその他の高度な概念は使用していません。

非同期アクションクリエーターを抽出します

上記の方法は単純な場合にはうまく機能しますが、いくつかの問題が見つかる可能性があります:

  • 通知を表示したい場所にこのロジックを複製する必要があります。
  • 2 つの通知を表示するのに十分な速度がある場合、それらの通知には ID がないため、競合状態が発生します。最初のタイムアウトが経過すると、HIDE_NOTIFICATION が誤って送出され、2 番目の通知が途中で非表示になります。

これらの問題を解決するには、関数を抽出し、タイムアウト ロジックを一元化し、これら 2 つの操作をディスパッチする必要があります。以下に示すように:

// actions.js
function showNotification(id, text) {
  return { type: 'SHOW_NOTIFICATION', id, text }
}
function hideNotification(id) {
  return { type: 'HIDE_NOTIFICATION', id }
}

let nextNotificationId = 0
export function showNotificationWithTimeout(dispatch, text) {
  // 为通知分配 ID,这样 reducer 就可以忽略不当前可见通知的 HIDE_NOTIFICATION。
  // 或者,我们可以存储超时 ID 并调用 clearTimeout(),但是我们仍然需要在一个地方执行此操作。
  const id = nextNotificationId++
  dispatch(showNotification(id, text))

  setTimeout(() => {
    dispatch(hideNotification(id))
  }, 5000)
}

これで、コンポーネントは、このロジックを繰り返したり、別の通知との競合状態を発生させたりすることなく、showNotificationWithTimeout を使用して通知を表示できるようになります:

// component.js
showNotificationWithTimeout(this.props.dispatch, 'You just logged in.')

// otherComponent.js
showNotificationWithTimeout(this.props.dispatch, 'You just logged out.')    

showNotificationWithTimeout() ディスパッチを受け入れる理由最初のパラメータとして?操作をストアに送信する必要があるためです。通常、コンポーネントはディスパッチにアクセスできますが、外部関数にディスパッチ操作を制御してもらいたいため、外部関数に制御を与える必要があります。

モジュールから 1 つのストアをエクスポートした場合は、それをインポートしてその中で直接送信操作を実行できます:

store.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  store.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

見た目は単純ですが、 この方法はお勧めしません 。私たちがこれを好まない主な理由は、ストアをシングルトンにすることを強制することです。このため、サーバー側レンダリングの実装が非常に困難になります。サーバー側では、異なるユーザーが異なるプリロードデータを取得できるように、各リクエストに独自のストアを持たせる必要があります。

店舗が 1 つあるとテストも難しくなります。アクション クリエーターは特定のモジュールからエクスポートされた特定の実際のストアを参照するため、アクション クリエーターをテストするときにストアをモックできなくなりました。外部から状態をリセットすることもできません。

したがって、技術的にはモジュールから単一のストアをエクスポートできますが、そうすることはお勧めしません。アプリがサーバー側レンダリングを追加しないことが確実な場合を除き、これを行わないでください。

前のバージョンに戻ります:

this.props.dispatch({ type: 'SHOW_NOTIFICATION', text: 'You logged in.' })
setTimeout(() => {
  this.props.dispatch({ type: 'HIDE_NOTIFICATION' })
}, 5000)

これにより、重複ロジックの問題が解決され、競合状態が回避されます。

サンクミドルウェア

単純なアプリケーションの場合は、上記の方法で十分です。それで満足であれば、ミドルウェアについて心配する必要はありません。

しかし、大規模なアプリケーションでは、いくつかの不都合が見つかるかもしれません。

たとえば、ディスパッチを渡すのは残念なことのように思えます。これにより、コンテナ コンポーネントとプレゼンテーション コンポーネントを分離することが難しくなります。これは、上で説明したように Redux オペレーションを非同期で送信するコンポーネントは、ディスパッチをさらに渡すことができるように、ディスパッチを prop として受け入れる必要があるためです。 showNotificationWithTimeout() は実際にはアクション クリエーターではないため、connect() を使用してアクション クリエーターをバインドすることはできなくなりました。 Redux 操作は返されません。

また、どの関数が同期アクション作成者 (例: showNotification()) であり、どの関数が非同期ヘルパー関数 (例: showNotificationWithTimeout()) であるかを覚えるのは面倒な場合があります。これらをさまざまな方法で使用し、互いに混同しないように注意する必要があります。

ここで、このパターンをヘルパー関数に提供することを「正当化」し、Redux がそのような非同期アクションクリエーターを、さまざまな関数の完全な動機付けではなく、通常のアクションクリエーターの特別なケースとして「扱う」のに役立つ方法を見つけます。

それでもなおこの問題が自分のアプリケーションに存在すると主張し、そう思われる場合は、Redux Thunk ミドルウェアの使用を歓迎します。

簡単に言えば、Redux Thunk は Redux に、実際には関数である特殊なタイプの操作を認識するよう教えます:

// actions.js
export function showNotification(text) {
  return { type: 'SHOW_NOTIFICATION', text }
}
export function hideNotification() {
  return { type: 'HIDE_NOTIFICATION' }
}

// component.js
import { showNotification, hideNotification } from '../actions'

this.props.dispatch(showNotification('You just logged in.'))
setTimeout(() => {
  this.props.dispatch(hideNotification())
}, 5000)

このミドルウェアが有効な場合、関数を送信すると , Redux Thunk ミドルウェアはディスパッチをパラメータとして渡します。また、そのようなアクションを「食べる」ので、リデューサーが奇妙な関数引数を受け取ることを心配する必要はありません。リデューサーは、通常のオブジェクト操作 (直接送信されたもの、または先ほど説明したように関数によって送信されたもの) のみを受け取ります。

ダメみたいですね?今回の場合はそうではありません。ただし、これにより showNotificationWithTimeout() を通常の Redux アクション作成者として宣言できます:

this.props.showNotification('You just logged in.')
setTimeout(() => {
  this.props.hideNotification()
}, 5000)

以上がタイムアウトを指定して Redux アクションをディスパッチするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。