score:1

Accepted answer

you should listen to the hashchange event and update the state once it changed. to perform two-way binding you also should listen to the state changes and update window hash once the state changed. this is the idea of how it can work (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);

score:0

i was inspired by alexander bykov's answer + redux-persist and made this - an enhancer, that makes two-way binding of hash<->store.

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))
    }
  }
};

use like this:

export const store = createstore(
    reducer,
    initialstate,
    hashenhancer(hashfromstate, statefromstateandhash)
);

where hashfromstate is function of type hash=>state, and statefromstateandhash is function (state, hash) => state.

it might be overengineered and router would be simplier, i just don't understand react-router or react-router-redux at all.


Related Query

More Query from same tag