2016-05-10 12 views
10

Pracowałem nad projektem React & React. W projekcie wykorzystano oprogramowanie webpack-dev-middleware i gorące oprogramowanie pośrednie do szybkiego przeładowania.Redux Saga hot reloading

Po dodaniu sagi Redux do projektu i dodaniu oprogramowania pośredniego saga do sklepu redux. Wydaje się, że ilekroć zmienić kody Saga, gorące przeładunek wola złamał i wyświetla komunikat o błędzie:

Dostawca> nie umożliwia zmianę store w locie. Najprawdopodobniej widzisz ten błąd, ponieważ zaktualizowałeś Redux 2.x i React Redux 2.x, które już nie są automatycznie ładowane automatycznie. Instrukcje migracji znajdują się w sekcji https://github.com/reactjs/react-redux/releases/tag/v2.0.0.

Rozumiem, że Saga używa generatorów i jest zależna od czasu. Czy można ponownie załadować stronę za pomocą Sagas? tak jak reduktory Redux zastępują się podczas szybkiego przeładowywania.

Dzięki!

+0

Zobacz dyskusję https://github.com/yelouafi/redux-saga/issues/22#issuecomment-218522365 –

Odpowiedz

16

Pracuję nad projektem z redukcją i redukcją sagów (ale nie reaguję). Zaimplementowałem ponowne ładowanie sag za pomocą sagaMiddleware.run(), ale musisz obsłużyć przeładowanie modułu i wymienić reduktory i sagi zgodnie ze wskazaniami podanego linku (https://github.com/reactjs/react-redux/releases/tag/v2.0.0).

import { createStore } from 'redux'; 
import rootReducer from '../reducers/index'; 
import getSagas from '../sagas'; 

export default function configureStore(initialState) { 
    const sagaMiddleware = createSagaMiddleware() 
    const store = createStore(rootReducer, initialState, applyMiddleware(sagaMiddleware)); 
    let sagaTask = sagaMiddleware.run(function*() { 
    yield getSagas() 
    }) 
    if (module.hot) { 
    // Enable Webpack hot module replacement for reducers 
    module.hot.accept('../reducers',() => { 
     const nextRootReducer = require('../reducers/index'); 
     store.replaceReducer(nextRootReducer); 
    }); 
    module.hot.accept('../sagas',() => { 
     const getNewSagas = require('../sagas'); 
     sagaTask.cancel() 
     sagaTask.done.then(() => { 
     sagaTask = sagaMiddleware.run(function* replacedSaga (action) { 
      yield getNewSagas() 
     }) 
     }) 
    }) 
    } 

    return store; 
} 

Należy zwrócić uwagę na funkcję getSagas(). Zwraca tablicę świeżo utworzonego obiektu generatora sag, nie możesz mieć jakiegoś wstępnie przygotowanego obiektu w tablicy z niektórych już uruchomionych sag. Jeśli tę tablicę buidujesz tylko w jednym module, możesz użyć bezpośrednio stałej tablicy, ale jeśli ją zbudujesz komponując sagi z różnych modułów, musisz odtworzyć sagi ze wszystkich modułów, więc lepszym rozwiązaniem jest to, że wszystkie funkcja tworzenia eksportu modułów zamiast eksportowania stałej sagi lub tablicy sag. Na przykład może to być funkcja tak:

export default() => [ 
    takeEvery(SOME_ACTION, someActionSaga), 
    takeEvery(OTHER_ACTION, otherActionSaga), 
] 

Oczywiście wszystkie sagi są wznowiona od początku, a jeśli masz skomplikowany sagi ze stanu wewnętrznego tracisz aktualny stan.

Bardzo podobnym podejściem jest użycie dynamicznej sagi zamiast wywoływania sagaMidleware.run(), to bardzo podobne rozwiązanie, ale możesz przeładować podzbiory sag i obsługiwać je na różne sposoby. Aby uzyskać więcej informacji, zobacz https://gist.github.com/mpolci/f44635dc761955730f8479b271151cf2

+1

Rozwiązałem mój problem. @kevin, możesz oznaczyć tę odpowiedź jako poprawną, jeśli rozwiązała Twój problem. – wrick17

+0

@mpolci możesz wyjaśnić więcej o funkcji getSagas? Rozumiem, że chcesz uzyskać szereg obiektów generujących sagę, ale jeśli masz wiele plików sagi, które eksportują słuchaczy, czy poleciłbyś zaimportowanie każdego z nich i wywołanie ich jako łańcucha? 'import getSaga1 z '../ saga1'' import getSaga2 z' ../ saga2', a następnie w sagaTask 'getSaga1() getSaga2()' – mattgabor