Open yyynnn opened 5 years ago
Thanks for the question, I'll take a closer look at this and see if I can figure out what is going on and how to solve.
I wasn't sure in your example whether you have dispatched the action(s) before calling whenComplete on your SSR.
Does your actions.data().type action get dispatched before the store.logicMiddleware.whenComplete() is called? That would be key for this to work, all actions need to be dispatched so things are in flight before whenComplete is called.
@jeffbski, well it is expected to be working while i do redux-logic-stuff in <ServerRoot/>
, i launch my actions to trigger logics there.
It worked with dispatching actions before <ServerRoot/>
explicitly. Like this:
//first
store.dispatch(someActions.actionTODO())
//then
const root = renderToString(
<ServerRoot
sizesConfig={sizesConfig}
location={req.url}
sheet={sheet.instance}
store={store}
context={context}
/>
)
//boom i got whole route in html with prefetched initial state for redux
But it is kinda bad. Doubling and what if some action names change?
It would be nice to trigger some special
logic that could terminate on will:
//first
store.dispatch(globalActions.trigger_special_logic_START())
//then
const root = renderToString(
<ServerRoot
sizesConfig={sizesConfig}
location={req.url}
sheet={sheet.instance}
store={store}
context={context}
/>
)
store.dispatch(globalActions.trigger_special_logic_END())
// like done() was triggered outside
I have this problem too
@jeffbski is there anything that can be done with this problem? Or am i doing something wrong?
Sorry for the delay on this, slipped off my radar.
I'm not sure if I completely understand what you are proposing? Let me suggest what I think you are wanting to accomplish and if I am missing the mark, let me know.
If you simply want to wait for state to finish changing before continuing then what about something like this?
//first
store.dispatch(globalActions.trigger_special_logic_START())
//then
const root = renderToString(
<ServerRoot
sizesConfig={sizesConfig}
location={req.url}
sheet={sheet.instance}
store={store}
context={context}
/>
)
// assuming you have put your logicMiddleware on the store when you created it,
// the promise completes when everything in redux-logic is done running
await store.logicMiddleware.whenComplete()
// now I am ready to deliver for SSR
I want to make this work well with SSR so if I am missing something please explain and we'll try to tackle it.
@jeffbski yeah, but the initial render will happen and data will not be in place. To make this work you need to do two renderToString calls (as i recall in redux-saga):
The data flow on server in this case is this (top to bottom):
// first ss render to string WILL MOUNT TRIGGER RENDER. data state is: List [] // initial render. empty data. RENDER TO STRING SYNC END LOGIC START DISPATCH. SIDE EFFECT SUCCESS LOGIC END WHEN COMPLETE TRIGGERED
// second ss render to string WILL MOUNT TRIGGER RENDER. data state is: List [ Map {} ] //data is finally here RENDER TO STRING 2-ND SYNC END // no need for logic call in ssr (could be resolved with a condition) LOGIC START DISPATCH. SIDE EFFECT SUCCESS LOGIC END
with this solution you can't escape the double render but it works with no code duplication.
So here is the working boilerplate https://github.com/yyynnn/redux-logic-ssr-boilerplate
You just do the first render to get the data, then you fire signal action to tell the server-side-redux-store, that you are on the second render, and inside logics you could get that value from the store to conditionally do logic and save some requests. Check the renderer.
@jeffbski: I know this is an old thread. Wondering if you had thoughts on the double-render. Does it sound necessary in all situations when using redux-logic, or only for specific ones?
I am also trying to figure out what needs to be waited on with whenComplete(). If I use redux-logic for API calls and websockets, it does not seem any of that logic would get activated during server side rendering and therefore would not need to be waited on (unless the API call needs to happen before the render). Now for something related to authentication, I am not sure.
@jeffbski: Any thoughts on this and how would this work with React 18 renderToPipeableStream?
Hi there! Great lib. Having trouble getting state from api call while doing server side render. All i get is the initial state of the reducer. How to wait for store to get a new state? (using redux-logic, recompose)
Like whenComplete ignore logic completion