2017-06-21 48 views
1

我現在正在學習Redux和React,並且正在編寫一個像這樣工作的愛好項目。URL散列和Redux狀態的雙向綁定

該項目是一個搜索服務,使用標籤進行搜索。用戶可以在UI中添加或刪除標籤。在代碼中,標籤以Redux狀態表示,添加和刪除標籤通過單獨的操作發生。到目前爲止這麼好,我有一個有效的玩具代碼。

現在我想以某種方式將標籤與哈希後的URL部分「綁定」例如,序列化標籤,用破折號分隔;以便用戶可以複製/粘貼URL並使用相同的標籤。

我找不到如何輕鬆做到這一點。

我總是碰到一個叫做「react router」的東西,但我在示例中看到的所有東西總是有更多的輸入點,並根據哈希顯示用戶應用程序的不同部分。我不想那樣。所以我不知道我是否真的需要這個路由器;我不想任何路線。

即使我想這樣,我也找不到如何將URL與Redux狀態綁定。我不想將標籤直接注入組件的道具;我想要在Redux狀態下的url中的標籤。

感覺就像我做錯了事,我需要重新思考我的整體設計,但我不知道從哪裏開始。

(我沒加任何實際的代碼,因爲我認爲這是對應用程序的設計更具普遍性的問題,但後來我可以簡化我的玩具代碼,並將其粘貼在此處)

回答

1

你應該聽hashchange事件和更新狀態一旦改變。要執行雙向綁定,您還應該監聽狀態更改並在狀態更改後更新窗口哈希。這是它如何工作的想法(fiddle):

function changeHash(state = '', action) { 
    if(action.type == 'CHANGE_HASH') 
    return action.hash; 

    return state; 
} 

const store = Redux.createStore(changeHash); 

store.subscribe(() => { 
    const hash = store.getState(); 
    if (window.location.hash !== hash) { 
    window.location.hash = hash; 
    console.log('State changed: ' + hash); 
    } 
}); 

window.addEventListener("hashchange",() => { 
    const hash = window.location.hash; 
    if (store.getState() !== hash) { 
    store.dispatch({ 
     type: 'CHANGE_HASH', 
     hash 
    }); 
    console.log('Hash changed: ' + hash); 
    } 
}, false); 

setTimeout(() => { 
    store.dispatch({ 
    type: 'CHANGE_HASH', 
    hash: '#changed-state' 
    }); 
}, 3000); 

setTimeout(() => { 
    window.location.hash = '#changed-hash'; 
}, 6000); 
+0

檢查此示例與react-router-redux https://fiddle.jshell.net/omerts/r9dbgsjj/ –

+0

該示例不與最新的react-router –

+0

一起工作我做了一個相同的增強器,但我會選擇你的答案,因爲我複製了那裏最重要的部分 –

0

我被亞歷山大貝科夫的答案+終極版 - 堅持鼓舞,這一點 - 增強,使雙向綁定的散列<的 - >商店。

import { applyMiddleware } from 'redux'; 
import createActionBuffer from 'redux-action-buffer'; 

const CHANGE_HASH = '@@hashSynch/CHANGE_HASH'; 
const hashEnhancer = (hashFromState, stateFromStateAndHash) => createStore => (reducer, initialState) => { 
    const store = createStore(liftReducer(reducer), initialState, applyMiddleware(createActionBuffer(CHANGE_HASH))); 
    store.subscribe(() => { 
    const hash = hashFromState(store.getState()); 
    if (window.location.hash !== hash) { 
     window.location.hash = hash; 
    } 
    }); 

    window.addEventListener('hashchange',() => { 
    const hash = window.location.hash; 
    const savedHash = hashFromState(store.getState()); 
    if (savedHash !== hash) { 
     store.dispatch({ 
     type: CHANGE_HASH, 
     hash 
     }); 
    } 
    }, false); 

    store.dispatch({ 
    type: CHANGE_HASH, 
    hash: window.location.hash 
    }); 

    function liftReducer(reducer) { 
    return (state, action) => { 
     if (action.type !== CHANGE_HASH) { 
     return reducer(state, action); 
     } else { 
     return stateFromStateAndHash(state, action.hash); 
     } 
    } 
    } 

    return { 
    ...store, 
    replaceReducer: (reducer) => { 
     return store.replaceReducer(liftReducer(reducer)) 
    } 
    } 
}; 

使用這樣的:

export const store = createStore(
    reducer, 
    initialState, 
    hashEnhancer(hashFromState, stateFromStateAndHash) 
); 

其中hashFromState是類型散列=>狀態的功能,並且是stateFromStateAndHash功能(狀態,散列)=>狀態。

它可能是過度工程和路由器會更簡單,我只是不明白react-router或react-router-redux。