Repository navigation
fixing React.createContext in SSR #40
Description
Activity
As another reference, I've recently fixed the
graphql-reactSSRpreloadfunction for React v16.6 context: Diff here.@tadeuszwojcik of course, always happy to keep inline with the latest fixes and enhancements that the Apollo team have applied. Would really appreciate the PR. 👍
Any updates on this? I have problems updating to react 16.6.x which makes react-async-bootstrapper unusable.
Reacted by Dan, Nikita Razmakhnin and 龙泉月夕@ctrlplusb Any idea when you'll be releasing this? We're using
react-tree-walkerover at next-i18next. Thanks!Reacted by Javier, Arthur and Nikita RazmakhninSeems like @ctrlplusb is inactive, it's a bit annoying. Did anyone create a fork and published it on npm?
@isaachinman @jcampalo Did you guys publish a fork by any chance?
Hi @oyeanuj. Over at next-i18next I had to move away from
react-tree-walkerentirely due to:- Performance impact.
- Unreconcilable issues with context.
It's a bit of a shame, but I think this project is self-aware in that it's not appropriate for every use case.
Good luck!
@isaachinman what did you end up using instead?
@oyeanuj I took a completely different approach that sidestepped tree traversal entirely. Sorry if that's not helpful.
@ctrlplusb Please give proper rights to others, we need this fix.
Shit. completely stuck on this. Days sunk into this already. What are people using as alternatives?
@mschipperheyn I didn't personally check it myself, but see this: #46 (comment)
@mschipperheyn I didn't personally check it myself, but see this: #46 (comment)
I tested this and It did not solve this problem.
Does this fork fix the issue for anyone? It has worked for me. If so I can work on a PR w/ the fix I lifted from
react-apollo.React hooks is probably a bigger problem than the context API, a lot of libraries including
graphql-reactand Apollo have given up on walking React trees.Reacted by Dan and Markus J. WetzelYeah, I mean it's a large part of why I haven't even begun looking at Hooks. I need asynchronous components on the server side more than I need hooks. Unfortunately React.lazy + Suspense is useless until their new server renderer is done in the second half of this year so this will have to do.
Ah, I see what you mean now. Your solution in graphql-react and the new react-apollo getDataFromTree are interesting. I imagine it's a lot more expensive but the reliability is what matters most I guess.
Reacted by Jayden Seric and jdwillemseAfter the release of React Hooks I've moved away from
react-tree-walker.
I figured that it will be an endless fight to keep up with React. Very ambitious to say the least (just thinking about Suspense, Concurrent mode, etc.)In the end I decided to go the same way as
react-apollodid. Even if it's one more complete render cycle. I simplified it a lot for my use case.If anyone is interested that's how I've roughly done it.
// server.js // Preparation for SSR export const PreloadPromiseContext = React.createContext() // This will called on page load on SSR const preload = async tree => { const loaders = [] const registerLoader = loaderConfig => loaders.push(loaderConfig) // collect ReactDOMServer.renderToStaticMarkup( <PreloadPromiseContext.Provider value={{ registerLoader }}> {tree} </PreloadPromiseContext.Provider> ) // resolve one after another // loaders will put responses into global store for (const { props, loader } of loaders) { await loader(props) } } // Actual SSR server.use(async (req, res) => { const app = ( <Provider store={store}> <App /> </Provider> ) await preload(app) // use state and markup to render the actual HTML output const state = store.getState() const markup = ReactDOMServer.renderToString(app) })
Now this is used in combination with a HoC (could maybe be a hook at some point?) Every component which should preload is wrapped with this.
import PreloadPromiseContext from './server.js' const resolve = loader => Component => { class Resolve extends React.Component { static contextType = PreloadPromiseContext constructor(props, context) { super(props, context) if (context && typeof window === 'undefined') { // fetch on SSR context.registerLoader({ props, loader }) } else { // fetch on client side, to make life easier // (you might not need this) loader(props) } } render() { return <Component {...this.props} /> } } return hoistNonReactStatics(Resolve, Component) } // Example usage for a component. The result will be put in a global store inside the called function export default presolve(props => props.store.fetchThings())(MyApp)
Reacted by Jared Lunde, Matheus Portillo, Markus J. Wetzel, jdwillemse, John Grishin and Matej Vobornik
Hi,
would you consider making changes analogous to apollographql/react-apollo#2304 in order to fix context handling? I'm happy to create pull request for that if you'd like to.
Thanks!