Closed qw-in closed 7 years ago
Comin in a week or so. U gotta make the middleware respond to an action containing the new routes. As well as the reducer which also maintains a reference to it (but that is more standard).
It also may be possible to just update the reducer state and always read from state rather than closure. In a few places that might not be possible, but hopefully that's not the case.
Dynamically injecting routes would be great! I was looking for this feature too but did not find it.
Would be great being able to inject new routes when we async load a component we want to display. It's really a pain to have to declare all the possible routes at first.
Thanks for explanation btw
Assuming routesMap
can always be read from state, is there an argument to be made for not adding a specific action (like NOT_FOUND
) for modifying it?
// ...
const { reducer } = connectRoutes(history, routesMap);
// Note the lack of default value
const myReducer = (lastState, action) => {
const state = reducer(lastState, action);
switch (action.type) {
case 'MY_ACTION': {
return {
...state,
routesMap: {
...state.routesMap,
SOME_NEW_PATH: '/some/new/:path',
},
};
}
default:
return state;
}
};
const rootReducer = combineReducers({ location: myReducer });
// ...
Would be interested in your thoughts or any issues with this approach
a specific action is exactly what it will need no matter what, but i still need to look into the middleware and see if it can read from state.
ok, this is done. it's in the @next dist-tag on NPM. get it like this:
yarn upgrade redux-first-router@next
here's how you use it:
import { addRoutes } from 'redux-first-router'
import universal from 'react-universal-component'
const UniversalComponent = universal(props => import(`./${props.page}`), {
onLoad: module => {
const aThunk = addRoutes(module.newRoutes)
store.dispatch(aThunk)
}
})
this is just an example using Universal. you can use any code splitting component/tools you want.
So essentially you have an action creator now to dispatch new routes received via code-splitting.
There's one thing I'm noticing now that I'm using it with React Universal Component--onLoad
doesn't receive props, so a global store
variable had to be imported and used, which is no good. I'll have to add a 2nd props
arg there so your redux connected component can pass dispatch
. It should be:
onLoad: => (module, props) => props.dispatch(addRoutes(module.newRoutes))
I'll make that tweak in RUC.
For now if you're looking at this and interested, find a way to access store
directly or if you're using other code splitting tools, you know what to do.
Otherwise, i'm closing this issue. feel free to open any specific new Issues. Feel free to add some docs about this. 🚀
Thanks! Looks awesome!
Unfortunately don't have time to mess with it at the moment but looking forward to it. If there is still a need for docs when I get time to check it out I'll put something together. Maybe this weekend
Ok, React Universal Component has been updated to better support the various things you might wanna do when code-splitting. The onLoad
option now receives both props
and context
. Context is passed so you don't need to import
your store, which is problematic when doing SSR where you must have the store
corresponding to the specific express request. Here's what this looks like:
import { addRoutes } from 'redux-first-router'
import universal from 'react-universal-component'
const UniversalComponent = universal(props => import(`./${props.page}`), {
onLoad: (module, info, props, context) => {
const aThunk = addRoutes(module.newRoutes) // export new routes from component file
context.store.dispatch(aThunk)
context.store.replaceReducer({ ...otherReducers, foo: module.fooReducer })
// if a route triggered component change, new reducers needs to reflect it
context.store.dispatch({ type: 'INIT_ACTION_FOR_ROUTE', payload: { param: props.param } })
}
})
do yarn upgrade react-universal-component
if that's what you're using for code splitting.
addRoutes
is missing from npm versions later than 0.0.9-next
@defualt sorry about that. it's back in.
+ redux-first-router@0.0.20-next
@faceyspacey can you share your configureStore from this last example? `import { addRoutes } from 'redux-first-router' import universal from 'react-universal-component'
const UniversalComponent = universal(props => import(./${props.page}
), {
onLoad: (module, info, props, context) => {
const aThunk = addRoutes(module.newRoutes) // export new routes from component file
context.store.dispatch(aThunk)
context.store.replaceReducer({ ...otherReducers, foo: module.fooReducer })
// if a route triggered component change, new reducers needs to reflect it
context.store.dispatch({ type: 'INIT_ACTION_FOR_ROUTE', payload: { param: props.param } })
} })`
How are you combining the new reducer with the already loaded ones and keeping the state?
I was recently working on a webapp for work and started messing around with per-client routing (it's a private webapp, SEO is not of concern). I currently have it implemented with slugs
/:client/:thing
but that was only after I tried wrapping the redux-first-router reducer to allow injecting new routes into theroutesMap
on the fly.I was a bit disappointed to find that when I changed the routesMap in the redux store that change was not reflected by the middleware / enhancer. I had a brief poke through the code and it seems that this is due to the routesmap being passed into the enhancer when
connectRoutes
is called. I would assume it is possible for the enhancer to read theroutesMap
from the store instead.So I suppose I am wondering if there would be any large issues if this was implemented. To my understanding it would change nothing in terms of the API (unless it had to be specifically enabled in the
connectRoutes
options). Certainly not a high priority feature but it would be nice to be able to define more solid routes for each client.