2017-11-07 6 views
0

React with Redux Sagaでアプリケーションを実装しようとしていますが、特定のユースケースの情報がそこにどれだけ少ないのか、それは奇妙に見えません。おそらく私は間違った言葉を使ったり、間違った方法で問題を考えているのですが、私はReact/Reduxの方がはるかに新しいです。いずれにせよ、私はこの問題をGoogleに挑戦しようとするすべての試みに悩まされており、私よりもフレームワークの経験が豊富な人からいくつかの洞察に感謝しています。Redux Sagaで個々の状態プロパティを更新するためのベストプラクティス

私のアプリケーション状態には、ログインしたユーザーのいくつかの構成オプションを管理するuserSettingsというプロパティがあります。アプリケーションのある時点で、ユーザーはスイッチをフリップして「一見」ダッシュボードウィジェットの表示を無効にすることができます。この情報をバックエンドAPIに渡して、データベース内の設定情報を更新してから、このバックエンド更新が成功したかどうかに従って状態を更新します。

私のコード、それは私がこのように、特にこの設定のために、より具体的な武勇伝を経由して到達する予定のすべてのユーザー設定の更新のための主要な武勇伝を持っている現在立っているよう:

Dashboard.js

function mapStateToProps(state) { 
    const { userSettings } = state; 
    return { userSettings }; 
} 
... 
class Dashboard extends Component { 
    ... 
    ... 
    hasDashboardAtAGlanceHiddenToggle() { 
     const { dispatch, userSettings } = this.props; 
     dispatch(setHasDashboardAtAGlanceHidden(!userSettings.hasDashboardAtAGlanceHidden)); 
    } 
} 
export default connect(mapStateToProps)(Dashboard); 

updateUserSettingsSaga.js

import { take, put, call } from 'redux-saga/effects'; 
import axios from 'axios'; 

import { 
    UPDATE_USER_SETTINGS, 
    SET_HAS_DASHBOARD_AT_A_GLANCE_HIDDEN, 
    updateUserSettings, 
    updatedUserSettingsSuccess 
} from '../../actions'; 

export function* setHasDashboardAtAGlanceHiddenSaga() { 
    const action = yield take(SET_HAS_DASHBOARD_AT_A_GLANCE_HIDDEN); 
    const newValue = action.data; 
    //QUESTION HERE -- how to get full object to pass to updateUserSettings 
    yield put(updateUserSettings(stateObjectWithNewValuePopulated)); 
} 

export default function* updateUserSettingsSaga(data) { 
    yield take(UPDATE_USER_SETTINGS); 
    try { 
     const response = yield call(axios.put, 'http://localhost:3001/settings', data); 
     yield put(updatedUserSettingsSuccess(response.data)); 
    } catch (e) { 
     yield put(updatedUserSettingsFailure()); 
    } 
} 

マイ質問は、コードに書かれているように、私は、どのようにして、どのようにして状態に更新された値をマージさせるべきかがわからないということです。すなわち、

  1. が最初のアクションをディスパッチする前に、コンポーネントで更新された状態をビルドします:

    hasDashboardAtAGlanceHiddenToggle() { 
        const { dispatch, userSettings } = this.props; 
        const newState = Object.assign({}, userSettings , { 
         hasDashboardAtAGlanceHidden: !userSettings.hasDashboardAtAGlanceHidden 
        }); 
        dispatch(setHasDashboardAtAGlanceHidden(userSettings)); 
    } 
    

    }

  2. 使用redux-私が理解できるように近いように、私は3つのオプションを持っていますサガのselectエフェクトを使用して、より具体的な初期サガのフル状態オブジェクトを作成します。つまり、

    export function* setHasDashboardAtAGlanceHiddenSaga() { 
        const action = yield take(SET_HAS_DASHBOARD_AT_A_GLANCE_HIDDEN); 
        const newValue = action.data; 
        const existingState = select(state => state.userSettings); 
        const updatedState = Object.assign({}, existingState, { 
         hasDashboardAtAGlanceHidden: newValue 
        }); 
        yield put(updateUserSettings(updatedState)); 
    } 
    
  3. はすなわち、それを更新する前に、オブジェクトのユーザー設定のサーバーのコピーを取得します。

    export default function* updateUserSettingsSaga() { 
        const action = yield take(UPDATE_USER_SETTINGS); 
        try { 
         const current = yield call(axios.get, 'http://localhost:3001/settings'); 
         const newState = Object.assign({}, current.data, action.data); 
         const response = yield call(axios.put, 'http://localhost:3001/settings', newState); 
         yield put(updatedUserSettingsSuccess(response.data)); 
        } catch (e) { 
         yield put(updatedUserSettingsFailure()); 
        } 
    } 
    

これらのすべてが(と思う)のオプションとして動作しますが、私は全く明確で、その上にはありませんよRedux Sagaのコンテキスト内での慣用的な/受け入れられた/好ましいアプローチであり、外部APIとのインターフェースをとるときにGETの代わりにPOST/PUTを使用する例が(少なくとも私が見つけることができた)驚くほど不足しています。私が間違った方法でこれについて考えているのであれば、どんな助けや指導も頂ければ幸いです。 :D

答えて

1

GET/PUT/POSTはこの質問には該当しません。全体的に、あなたの質問は本当にthe frequently asked question "How do I split logic between action creators and reducers?"になります。その答えを引用する:

リデューサーやアクションクリエイターには、どのようなロジックが必要か正確には明確な答えはありません。一部の開発者は、アクション内のデータを単純に取り込み、それを対応する状態に盲目的にマージする「薄い」リデューサを使用して、「太った」アクションクリエイターを持つことを好みます。他の人は、アクションを可能な限り小さく保つことを強調し、アクション作成者のgetState()の使用を最小限に抑えようとします。 (この質問の目的のために、サガやオブザーバなどの他の非同期アプローチは「アクションクリエイター」カテゴリに分類されます)。

あなたのレデューサーにもっと多くのロジックを入れることによっていくつかの潜在的な利点があります。アクションタイプは意味があり意味があります(「SET_STATE」ではなく「USER_UPDATED」など)。さらに、減速器でより多くのロジックを持つことは、タイムトラベルのデバッグによって多くの機能が影響を受けることを意味します。

このコメントはうまく二分法をまとめ:

さて、問題は、減速中のアクションの作成者とどのように置くためにどのような脂肪や薄いアクションオブジェクト間の選択です。アクションクリエータにすべてのロジックを置くと、基本的に状態への更新を宣言するファットアクションオブジェクトになります。レデューサーは純粋な、愚かな、追加、これを削除し、これらの機能を更新します。彼らは簡単に構成することができます。しかし、あなたのビジネスロジックの多くはそこにはありません。あなたがリデューサーにもっと多くのロジックを置くと、素敵なシンアクションオブジェクトとなり、データロジックの大半は1か所で処理されますが、他のブランチからの情報が必要な場合があるため、あなたは大型の減速機または減速機で終わります。減速機は国家の上から上がってくるからです。

また、私はしばらく前にmy own thoughts on "thick and thin reducers"を書きました。

究極的には、ロジックをどのように構成するかという問題です。

+0

素晴らしいです、ありがとうございます。 :)これは多くの助けとなりました。私はあまりにもこれを行うために正確な "正しい方法"があることにハングアップしていた、と私は思います。 – rosalindwills

関連する問題