は今

2016-05-01 17 views
1

Reduxの-サガとリダイヤルサーバー側を使用して、私はリダイヤルを通じて自分のアプリケーション・サーバー側の初期状態を取得しようとしています。は今

リダイヤルは純粋なオブジェクトアクションをトリガし、redux-sagaはそのアクションをリッスン/待機してから非同期リクエストを開始します。

しかし、問題は、純粋なオブジェクトをディスパッチしているため、redux-sagaが完了したときにリダイヤルが解決するという約束がありません。

コンポーネント

const redial = { 
    fetch: ({ dispatch }) => dispatch({ type: actionTypes.FETCH_START }), 
}; 

export default class PostList extends Component { 
    render() { 
     const { posts } = this.props; 
     return (
      <div> 
       {posts.map(post => <ListItem key={post.id} post={post} />)} 
      </div> 
     ); 
    } 
} 

PostList.propTypes = { 
    posts: PropTypes.array.isRequired, 
}; 

export default provideHooks(redial)(connect(mapStateToProps)(PostList)); 

佐賀

export function *fetch() { 
    try { 
     yield put({ type: actionTypes.FETCH_START }); 
     const response = yield call(fakeData); 
     yield put({ type: actionTypes.FETCH_SUCCESS, data: response.data }); 
     yield put({ type: actionTypes.FETCH_PENDING }); 
    } catch (e) { 
     yield put({ type: actionTypes.FETCH_FAIL }); 
    } 
} 

export default function *loadPost() { 
    yield * takeLatest(actionTypes.FETCH_START, fetch); 
} 

export default function *rootSaga() { 
    yield [ 
     fork(loadPost), 
    ]; 
} 

redux-sagaredialを接続する方法はありますか?

答えて

1

私はそれがこのような方法で行うことができると思う:

は、まず、あなたは地元の人で店を追加する必要があります。

const redial = { 
    fetch: ({ store, dispatch }) => { 
     return new Promise((resolve, reject) => { 
      const unsubscribe = store.subscribe(()=>{ 
       if (store.getState()...) { // monitor store state changing by your saga 
        resolve(...) //you probably dont need any result since your container can read them from store directly 
        unsubscribe(); 
       } 
       if (store.getState()....error) { 
        reject(...) 
        unsubscribe(); 
       } 
      }); 
      dispatch({ type: actionTypes.FETCH_START }), 
     } 
    } 
}; 

これらのコードは単なるデモンストレーション用である、適切なテストを行わず、生産に利用していない:

const locals = { 
    path: renderProps.location.pathname, 
    query: renderProps.location.query, 
    params: renderProps.params, 

    // Allow lifecycle hooks to dispatch Redux actions: 
    dispatch, 
    store 
}; 

は、その後、あなたは次のように手動での約束を作成することができます(コードがリダイヤルREADMEから取得されます)。

私は、状態がそれらのif(...)ステートメントに一致するまで、reduxストアの状態を何度もチェックするよりも、サガの実行結果を監視するより洗練された方法があると思うかもしれません。おそらくあなたはreduxストアと外部リスナーあなたの店舗構造について知る必要はありません。

0

これを行うにはかなりエレガントな方法があります。まず第一に、あなたのサガタスクのためのレジストリ(ミドルウェアの.runメソッドを実行すると、タスクディスクリプタを返すことに注意してください)を作成する必要があります。

export default class SagaTaskRegistry { 
    constructor() { 
    this._taskPromises = []; 
    } 

    addTask(task) { 
    if (!this._taskPromises) { 
     this._taskPromises = []; 
    } 
    this._taskPromises.push(task.done); 
    } 

    getPromise() { 
    return new Promise((resolve) => { 
     const promises = this._taskPromises; 
     if (!promises) { 
     resolve(); 
     return; 
     } 
     this._taskPromises = undefined; 
     Promise.all(promises).then(resolve).catch(resolve); 
    }).then(() => { 
     const promises = this._taskPromises; 
     if (promises) { 
     return this.getPromise(); 
     } 
     return undefined; 
    }); 
    } 
} 

あなたが.runを使用してサガミドルウェアに新しいタスクを追加し、あなたがして呼び出します。 registryInstance.add(taskDescriptor)SagaTaskRegistryは、そのタスクの約束をつかんで配列に追加します。

getPromiseを呼び出すと、追加されたすべてのタスクが完了すると解決される約束が表示されます。失敗したフェッチが拒否されることを望んでいない可能性が最も高いので、決して拒否されません。アプリケーションをエラー状態でレンダリングしたい場合もあります。

そして、これはあなたがredialとそれを組み合わせることができる方法です。

import createSagaMiddleware from 'redux-saga'; 
import { applyMiddleware, createStore } from 'redux'; 
import rootReducer from 'your/root/reducer'; 
import yourSaga from 'your/saga'; 

const sagaMiddleware = createSagaMiddleware(); 
const middleWare = [sagaMiddleware]; 
const createStoreWithMiddleware = applyMiddleware(...middleWare)(createStore); 
const store = createStoreWithMiddleware(rootReducer); 
const sagaTaskRegistry = new SagaTaskRegistry(); 
const sagaTask = sagaMiddleware.run(yourSaga); 
sagaTaskRegistry.addTask(sagaTask); 

match({ routes, history }, (error, redirectLocation, renderProps) => { 
    const locals = { 
    path: renderProps.location.pathname, 
    query: renderProps.location.query, 
    params: renderProps.params, 
    dispatch: store.dispatch, 
    }; 

    trigger('fetch', components, locals); 

    // Dispatching `END` will force watcher-sagas to terminate, 
    // which is required for the task promises to resolve. 
    // Without this the server would never render anything. 
    // import this from the `redux-saga` package 
    store.dispatch(END); 

    // The `SagaTaskRegistry` keeps track of the promises we have to resolve 
    // before we can render 
    sagaTaskRegistry.getPromise().then(...) 
}); 

コンポーネントは今簡単なフックで装飾することができます。うちにここから

const hooks = { 
    fetch: ({ dispatch }) => { 
    dispatch(yourAction()); 
    }, 
}; 

あなただけのようサガを使用することができますいつもこれは、あなたがしようとしていることをする能力を与える必要があります。これをさらに抽象化することで、コード分割チャンクなどでサガを動的に登録することができます。タスクレジストリは、実際に約束を解決する前に、getPromiseへの最後の呼び出し以降に新たに登録されたタスクをチェックすることによって、これらのユースケースに対して既に機能します。