2015-12-02 34 views
18

我有一個多步驟的表單應用程序,我正在努力解決如何保存我的redux狀態並在刷新後重播它的例子?在應用程序中後退/前進按預期工作,但在瀏覽器刷新後,我以前的狀態爲空。理想情況下,我希望能夠保存與路徑有關的會話存儲中的先前狀態,以便稍後重播,但我沒有看到我可以輕鬆地做到這一點。有沒有人做過這樣的事情,並可以提供一些指針?謝謝。Redux路由器 - 如何刷新後重播狀態?

回答

34

看起來您正嘗試在多頁面上下文中使用單頁面應用程序框架。爲了讓這兩種遊戲更好地結合在一起,你可以考慮讓自己的中間件與localStorage同步狀態,以創建一個在刷新/頁面導航後看起來沒有丟失任何狀態的應用程序。

  1. redux-logger日誌both the previous and next states,我可能會通過在createStoreWithMiddleware函數創建(redux-logger前右)的開頭(localStorageLoad)和結束(localStorageDump)在中間件封堵啓動方式相似:
// store/configureStore.js 

const createStoreWithMiddleware = applyMiddleware(
    localStorageLoad, thunk, promise, localStorageDump, logger 
)(createStore); 
  • 然後當你初始化應用程式之前應用程式呈現到加載存儲狀態觸發的初始動作右:
  • // index.js 
    
    const store = configureStore(); 
    
    store.dispatch({ type: 'INIT' }); 
    
    ReactDOM.render(<App />, document.getElementById('root')); 
    

    localStorageLoad將處理INIT行動,並派遣某種SET_STATE行動,其中將包含與先前保存在localStorage狀態的有效載荷。

    // middleware/localStorageLoad.js 
    
    export default store => next => action => { 
        const { type } = action; 
        if (type === 'INIT') { 
         try { 
          const storedState = JSON.parse(
           localStorage.getItem('YOUR_APP_NAME') 
          ); 
          if (storedState) { 
           store.dispatch({ 
            type: 'RESET_STATE', 
            payload: storedState 
           }); 
          } 
          return; 
         } catch (e) { 
          // Unable to load or parse stored state, proceed as usual 
         } 
        } 
    
        next(action); 
    } 
    

    然後,添加一個reducer,用該有效負載替換狀態,有效地重新啓動應用程序,就像以前一樣。

  • 要完成循環,你需要一箇中間件localStorageDump附帶在該保存每個還原態物體插入localStorage的鏈的末端。事情是這樣的:
  • // middleware/localStorageDump.js 
    
    export default store => next => action => { 
        const state = store.getState(); 
        localStorage.setItem('YOUR_APP_NAME', JSON.stringify(state)); 
        next(action); 
    } 
    

    只是一個想法,還沒有真正嘗試過。希望能幫助你開始尋求解決方案。

    +0

    完美,這看起來沿着正確的路線。出於某種原因,我被掛在使用路由而不是思考中間件。會給它一個去,但它是一個很好的出發點,謝謝! – Lee

    +0

    當然,祝你好運。關於REDX的一個很好的部分就是你最終得到的只是純粹的功能。您甚至可以在將它集成到您​​的應用程序之前,輕鬆地單元測試以上所有代碼。 – bosgood

    +0

    我發現這非常有用,我實現了一些可以從這裏提出的解決方案開始的工作。最終的解決方案有一些偏離這裏的建議,我想我應該分享。 首先,我沒有使用「INIT」方法來獲取初始狀態。相反,我只是在創建商店時加載了初始狀態。這可能違反規則,但這對我來說很有意義。它本質上是代碼localStorageLoad。 接下來,我使用了sessionStorage。這是一個挑逗,但一旦瀏覽器關閉並重新啓動,我寧願重新開始。我沒有空間...... – Scott

    2

    你不能在刷新狀態下存儲狀態,這是正常的。通常情況下,您將這些存儲在cookie或web存儲中。

    • Cookie在瀏覽器,服務器之間同步,並在您執行的每個請求中設置。
    • Localstorage爲您提供高達5MB的數據存儲空間,永遠不會發送請求。

    終極版:

    1. 在形式填充時設置的localStorage特性。 (請務必在完成時清除它)
    2. 使用不完整的表單刷新頁面。
    3. 當反應坐騎你Form組件,使用componentWillMount方法將localstoragedispatch數據讀取到減速
    4. 減速機更新了Redux-狀態,這又與你的localStorage得到屬性,更新的組件。

    如果使用redux來存儲表單數據,則調度localstorage的屬性。

    如果沒有讀取Form組件內的localstorage並設置初始值。

    希望這會有所幫助!

    +0

    我知道這是正常的行爲,但我希望有一種能力,可以將路由器上的redux狀態更改保存到特定路由的sessionStorage中,然後一次更新狀態。我知道redux-router會將路由信息保存到我的狀態中,我只是希望在應用程序範圍內而不是在組件級別執行此操作。 – Lee

    +0

    哦,你是說當你在你的應用中轉換到另一條路由時,你想要保存未完成表單的狀態?我誤解了,我認爲你的意思是當用戶「關閉標籤」和「重新訪問」應用程序時恢復狀態。 這實際上與路由器轉換沒有任何關係,而是redux存儲的內部狀態。您可能需要查看https://github.com/erikras/redux-form 這會將表單狀態保存在redux存儲區中。所以,即使你轉換回來,狀態仍然是相同的形式,除非你另有說明,並通過正確的道具。 – JensDebergh

    +0

    不,基本上當用戶從A轉換到B時,我希望將狀態存儲爲A,以便在基於URL返回B(刷新等)時可以重新加載它。但是如果可能的話,我想要廣泛地應用這個應用程序,而不是每個組件。基本上允許熱載入,而不用重構所有的使用webpack(目前使用browserify)。 – Lee

    相關問題