2016-05-01 88 views
1

現在,我想通過重撥讓我的應用程序的服務器端的初始狀態。使用終極版,傳奇和重撥服務器端

重撥觸發純對象的動作,和終極版-佐賀偵聽/等待該操作,然後啓動異步請求。

但問題是,重撥沒有承諾解決的時候,因爲它是分派純對象終極版,傳奇的完成。

組件

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), 
    ]; 
} 

是否有redial連接到redux-saga的方法嗎?

回答

1

我認爲它可以通過這種方式來完成:

首先,您需要添加店本地人。 (碼重撥自述拍攝)

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

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

然後,您可以手動創建一個承諾如下:

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 }), 
     } 
    } 
}; 

這些代碼只是爲了演示,在生產中不正確的測試不使用它們。

我覺得可能是一個監視一遍又一遍地檢查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以來新註冊的任務。