我现在正在学习Redux和React,我正在写一个像这样工作的爱好项目。
该项目是一个使用标签进行搜索的搜索服务。用户可以在UI中添加或删除标签。在代码中,标记以Redux状态表示,添加和删除标记通过单独的操作发生。到目前为止一切顺利,我有一个可行的玩具代码。
现在我想以某种方式将标签“绑定”到散列后的URL部分;例如,序列化标签,用短划线分隔;这样用户就可以复制/粘贴URL并使用相同的标签。
我无法轻易找到如何做到这一点。
我总是打一个叫做“反应路由器”的东西,但我在示例中看到的总是有更多的输入点到应用程序并根据哈希显示用户不同的应用程序部分。我不希望这样。所以我不知道我是否真的需要这个路由器;我不想路过任何东西。
即使我想要这个,我也找不到如何将Redux状态与URL绑定。我不想将标签直接注入组件的道具;我想要Redux状态的url中的标签。
感觉我做错了,我需要重新考虑我的整体设计,但我不知道从哪里开始。
(我没有添加任何实际代码,因为我认为它是关于应用程序设计的更普遍的问题,但我可以稍后简化我的玩具代码并将其粘贴到此处)
答案 0 :(得分: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);
答案 1 :(得分:0)
我受到Alexander Bykov的回答+ redux-persist的启发,并使这个 - 一个增强器,它使哈希< - >商店的双向绑定。
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是hash => state类型的函数,stateFromStateAndHash是function(state,hash)=>状态。
可能是过度设计,路由器会更简单,我根本不理解react-router或react-router-redux。