Reduxで状態を更新した後にコールバックをトリガーする方法は?


86

Reactでは、状態はすぐには更新されないため、でコールバックを使用できますsetState(state, callback)。しかし、Reduxでそれを行う方法は?

を呼び出した後、this.props.dispatch(updateState(key, value))すぐに更新された状態で何かをする必要があります。

Reactで行うように、最新の状態でコールバックを呼び出す方法はありますか?


使っていthunkますか?
Pranesh Ravi 2016

1
dispatch()同期的な活動だと思います。更新された状態は、次の行で利用できるはずです。
Pranesh Ravi 2016

4
@PraneshRaviそう思いました。しかし、私は古い状態になりました。使用しませんでしたthunk
ブリックヤン


1
はい、ディスパッチは同期的ですが、コンポーネントの小道具のその後の更新は同期的ではありません。したがって、reduxの状態は次の行で更新されますが、コンポーネントの小道具はまだ更新されていません。
AMIK

回答:


113

新しい小道具を受け取るには、コンポーネントを更新する必要があります。

あなたの目標を達成する方法があります:

1. componentDidUpdateは、値が変更されているかどうかを確認してから、何かを実行します。

 componentDidUpdate(prevProps){
     if(prevProps.value !== this.props.value){ alert(prevProps.value) }
  }

2. redux-promise(ミドルウェアはpromiseの解決された値をディスパッチします)

export const updateState = (key, value)=>
Promise.resolve({
  type:'UPDATE_STATE',
  key, value
})

その後、コンポーネントで

this.props.dispatch(updateState(key, value)).then(()=>{
   alert(this.props.value)
})

2. redux-thunk

export const updateState = (key, value) => dispatch => {
  dispatch({
    type: 'UPDATE_STATE',
    key,
    value,
  });
  return Promise.resolve();
};

その後、コンポーネントで

this.props.dispatch(updateState(key, value)).then(()=>{
   alert(this.props.value)
})

6
あなたのredux-thunkdispatchでは、同期しているように使用します。そうですか?
ダニーハーディング

2
@DannyHardingdispatchは同期していません。なければPromise.resolve()this.props.valueまだ古い値を返します。ある種の非同期延期がまだ必要です(setTimeoutたとえば、内部からの参照も機能します)。
Drazen Bjelovuk 2018

4
@DrazenBjelovuk redux-thunkの例のupdateState関数にはdispatch(someAction)があり、その直後にPromise.resolve()が返されるので疑問に思っています。約束はすぐに解決されます。これにより、reduxストアの更新とコンポーネントで呼び出される間の競合状態が発生すると思います。ディスパッチはpromiseを返したり、コールバックを受け入れたりしないため、これがreduxストアがいつ更新されたかを知る正確な方法ではないと思います。この場合、ジャストボリスによる答えは正しいと思います
Danny Harding

2
@DannyHardingええ、この方法は確実な火災保証ではない可能性が高いことに同意します。ディスパッチが同期していないことを示しているだけです。
Drazen Bjelovuk 2018

1
ここでredux-thunkソリューションを使用しようとしていますが、取得できTypeError: _this.props.dispatch is not a functionますか?
Krillko

14

Reactの最も重要なポイントは、一方向のデータフローです。つまり、あなたの例では、アクションのディスパッチと状態変更の処理を切り離す必要があります。

以下のようにあなたが考えるべきではありません「私はA、今XになっYて、私はそれを扱う」が、「とき、私は何をしますかXなったYとは無関係に、」A。ストアの状態は、コンポーネントに加えて、複数のソースから更新できます。TimeTravelも状態を変更でき、Aディスパッチポイントを通過しません。

基本的componentWillReceivePropsには、@ Utroによって提案されたとおりに使用する必要があることを意味します


これは、opが本当に探している答えです(彼はこれに気付いていないようですが..)
refaelio18年

1
私は同意するが、これはアンチパターンと考えているようです:hackernoon.com/...
ジャコモCerquone

1
componentWillReceiveProps非推奨になった今、私たちは何をしますか?static getDerivedStateFromProps()私が知る限り、コールバックを呼び出すことができないため、適切な代替品ではないようです
M3RS 2018年

9

Hooks APIの場合:

useEffect 小道具を入力として使用します。

import React, { useEffect} from 'react'
import { useSelector } from 'react-redux'

export default function ValueComponent() {
   const value = useSelector(store => store.pathTo.value)

   useEffect(() => {
     console.log('New value', value) 
     return () => {
        console.log('Prev value', value) 
     }

   }, [value])

   return <div> {value} </div>
}

受け入れられた回答は、ReactHooksの前に書かれました。これは、フックの導入後、現在受け入れられている答えになるはずです。これは、変更を処理するためのより反応的な方法です。
TIF

5

subscribeリスナーを使用でき、アクションがディスパッチされたときに呼び出されます。リスナーの内部では、最新のストアデータを取得します。

http://redux.js.org/docs/api/Store.html#subscribelistener


2
subscribeアクションがディスパッチされたときにのみ発生します。subscribeAPI呼び出しがデータを返したかどうかを通知する方法はありません。:D
Mihir 2016

リクエストが完了したとき(成功または失敗)に、別のアクションをディスパッチできます。
ジャム

状態が更新された後に解決する約束やコールバックを実行する方法がわからないため、ここで提案されている他のソリューションのいずれかが実際に機能するかどうかはわかりません。このメソッドは、イベント後に発生するものだけでなく、ストアの更新ごとに呼び出されますが、回避するのはそれほど難しいことではありません。特に、リンク先のページからカスタムobserveStoreユーティリティを作成するリンクは非常に役立ちます。
ナット・クーン

リンクページが見つかりません
BharatModi20年

2

コールバックでサンクを使用できます

myThunk = cb => dispatch =>
  myAsyncOp(...)
    .then(res => dispatch(res))
    .then(() => cb()) // Do whatever you want here.
    .catch(err => handleError(err))

私が必要としていたものにぴったりです!
JSON C11

-1

簡単な解決策として、次のものを使用できます: redux-promise

ただし、redux-thunkを使用している場合は、次のようにする必要があります。

function addCost(data) {
  return dispatch => {
    var promise1 = new Promise(function(resolve, reject) {
      dispatch(something);
     });
    return promise1;
  }
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.