2017-06-21 43 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。