2016-05-10 16 views
10

Tôi đang làm việc trên một dự án React & Redux. Dự án được sử dụng để sử dụng webpack-dev-middleware và phần mềm trung gian nóng để tải lại nóng.Redux Saga hot reloading

Sau khi tôi thêm Redux Saga vào dự án và thêm phần mềm trung gian saga vào kho lưu trữ Redux. Dường như bất cứ khi nào tôi thay đổi mã saga, việc tải lại nóng sẽ bị hỏng và hiển thị thông báo lỗi:

Nhà cung cấp> không hỗ trợ thay đổi store khi đang di chuyển. Rất có thể bạn sẽ thấy lỗi này vì bạn đã cập nhật thành Redux 2.x và React Redux 2.x mà không còn tự động tải lại bộ giảm tải nóng nữa. Xem https://github.com/reactjs/react-redux/releases/tag/v2.0.0 để biết hướng dẫn di chuyển.

Tôi hiểu rằng Saga sử dụng máy phát và tùy thuộc vào thời gian. Có thể tải lại trang nóng bằng Sagas không? giống như cách Redux giảm thay thế chính nó trong quá trình tải lại nóng.

Cảm ơn!

+0

Xem thảo luận https://github.com/yelouafi/redux-saga/issues/22#issuecomment-218522365 –

Trả lời

16

Tôi đang làm việc trên một dự án có redux và redux-saga (nhưng không phản ứng). Tôi đã cài đặt relaging hot sagas bằng cách sử dụng sagaMiddleware.run() nhưng bạn phải xử lý nạp lại module và thay thế các bộ giảm và sagas như được chỉ ra trong liên kết mà bạn cung cấp (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; 
} 

Điều quan trọng cần lưu ý là chức năng getSagas(). Nó trả về một mảng đối tượng máy phát mới được tạo ra của sagas, bạn không thể có một số đối tượng được xử lý trước trong mảng từ một số sagas đã chạy. Nếu bạn bẻ mảng này chỉ trong một mô-đun, bạn có thể sử dụng trực tiếp một mảng không đổi, nhưng nếu bạn xây dựng nó soạn sagas từ các mô-đun khác nhau, bạn phải chắc chắn tạo lại sagas từ tất cả các mô-đun, vì vậy cách tốt hơn là tất cả mô-đun xuất chức năng tạo thay vì xuất một saga cố định hoặc mảng sagas. Ví dụ nó có thể là một chức năng như thế này:

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

Rõ ràng tất cả các saga được khởi động lại từ đầu và nếu bạn có một saga phức tạp với trạng thái nội bạn mất trạng thái hiện tại.

Cách tiếp cận rất tương tự là sử dụng một câu chuyện động thay vì gọi sagaMidleware.run(), nó là một giải pháp rất giống nhưng bạn có thể tải lại các tập hợp con của các sagas và xử lý chúng theo nhiều cách khác nhau. Để biết thêm thông tin, hãy xem https://gist.github.com/mpolci/f44635dc761955730f8479b271151cf2

+1

Giải quyết được vấn đề của tôi. @ kevin, bạn có thể đánh dấu đây là câu trả lời đúng nếu nó đã giải quyết được vấn đề của bạn. – wrick17

+0

@mpolci bạn có thể giải thích thêm về hàm getSagas không? Tôi hiểu rằng bạn muốn nhận được một mảng các đối tượng máy phát điện saga, nhưng nếu bạn có nhiều tệp saga xuất các trình nghe, bạn có nên giới thiệu mỗi người và gọi chúng là một chuỗi không? 'import getSaga1 từ '../ saga1'' nhập getSaga2 từ' ../ saga2' và sau đó trong sagaTask 'getSaga1() getSaga2()' – mattgabor

Các vấn đề liên quan