react-ssr-error-boundary icon indicating copy to clipboard operation
react-ssr-error-boundary copied to clipboard

Support new Context API

Open overlookmotel opened this issue 6 years ago • 7 comments

Hi.

Would it be difficult to support the newer Context API released in React 16.3?

As I'm sure you're aware, this module solves one of the big problems standing in the way of implementing a "userland" version of Suspense which works on the server side. But, as I see it, the complications around Context are a bit of deal-breaker at present. The new Context API is used by React Router, for example.

I guess the ideal would be to automatically propagate context from all providers higher up the tree into the sub-tree passed to renderToStaticMarkup(). Ideally the component implementing an error boundary shouldn't need to be aware what providers are in use higher up the tree.

I have no idea whether React exposes current contexts in some private property which can be hooked into.

I'd be very happy to help with this, but sounds like you understand the internals of React much better than me, so any pointers to where to start would be much appreciated.

overlookmotel avatar Jan 06 '19 10:01 overlookmotel

Hello! Sorry for long wait, I had some troubles with github notifications 😅. Thank you for your PR! Monkey-patching react for SSR seems like a good idea.I think, it would be great if we could monkey-patch react a couple more times for remove shim function.

zekchan avatar Apr 02 '19 11:04 zekchan

This is a clever solution, but it doesn't solve the problem reliably.

Shimming the React.createContext function gives us a way to enumerate all active contexts, which then allows us to consume and re-provide the values of all the contexts, which allows the context to exist inside the inner renderToStaticMarkup.

The new problem is that we can't count on the order of execution of the code from separate modules. The shim code must execute before anyone calls createContext. If you use react-redux, that module calls createContext when it's module loads. If you load both modules, you have to ensure that your shim executes before react-redux is loaded. This is a race condition at best, or some hacky compile order requirements at worst. Either way, it's something that doesn't work without some non-standard hoop jumping. Many of the components which use contexts create the context globally at module load time, which is the worst possible case for this solution.

mnebuerquo avatar Jul 22 '19 15:07 mnebuerquo

@mnebuerquo I don't know if you're referring to using this for rendering Suspense on the server side or not. But if you are, I've published a separate module for this purpose:

https://www.npmjs.com/package/react-async-ssr

That supports both the old and new context APIs + also .useContext() hook.

overlookmotel avatar Jul 22 '19 16:07 overlookmotel

Suspense is an interesting module. I'm doing something similar with SSR, error boundaries, and lazy loading, but in a very large project with a custom framework on top of React. I've had to solve the same problems as you did in this repo, and I've hit the same difficulty with contexts.

The Hard Question for me is this one: How do you ensure that the shim function has executed before react-redux calls React.createContext?

mnebuerquo avatar Jul 22 '19 17:07 mnebuerquo

I don't use Redux so can't comment on that specifically.

I use a different shim in react-async-ssr - shim is applied on consumer, not provider, so it'll likely work fine . Have a look at the source code if you're interested. All I can say is there are a lot of tests on react-async-ssr covering all the cases I could think of, so I'm pretty confident it works.

By the way, I'm not a maintainer on react-ssr-error-boundary - I just raised this issue, but then went on and wrote my own module instead.

overlookmotel avatar Jul 22 '19 17:07 overlookmotel

I'm not using the shim in my solution now. I've just exposed an addContext function which you have to call to allow your context to pass through the wrapper. It's not an automatic solution, but it works. This is the only part of the SSR error boundary that doesn't make me happy.

mnebuerquo avatar Jul 24 '19 12:07 mnebuerquo

@mnebuerquo Interesting.

Please do have a look at react-async-ssr if you have a chance. It think it covers your use case in terms of SSR rendering Suspense, and it is fully "automatic".

I'd be very happy to receive a PR adding support for error boundaries too if you found it simple to add the code you've already developed for this.

overlookmotel avatar Jul 24 '19 13:07 overlookmotel