How to resolve React suspense on the server - reactjs

In my web app I would like to render most of my content on the server and serve complete HTML. Also, I would like for each React component to fetch its own data. I don't like the Next.js' approach of "fetch the data for the whole page". React suspense seems to be a good tool for this but suspense is never resolved on the server. The best you can do with React 18 is to renderToPipeableStream but then the actual content is still being constructed on the client by injecting script tags. That's not what I want. I want plain old HTML generated on the server.
I am now using react-ssr-prepass which works fine with React 17 but it is not suited to React 18.
Is there some way to achieve this? It seems to me it would be quite common usecase.

Check react-streaming. It's the only library that helps at the moment but it's still experimental

Related

How can I use ERB inside a React component? [Rails 6]

I have a project on Rails 6.
Started migrating it to React by using react-rails. However, there are still some components which I cannot migrate to React ATM due to time limitations.
I want to be able to use the old component (partial) in my React component.
e.g let's say I have a React component:
Component.tsx
export const Component = ({post}) => {
return <div>
<ShareButton post={post}/>
</div>
}
and somehow the ShareButton should contain this:
<%= render partial: 'posts/shared/share_post_btn', locals: {event: false, post: post} %>
I read that it may be possible by using .jsx.erb but I couldn't figure out how.
Would love to get some insights!
Thank you.
I'm afraid you'll be mixing build pipelines here. The .erb is parsed by the asset pipeline, which was the default for Rails <6 and still for CSS, but this doesn't work no longer by default for yarn/webpacker-based builds that Rails 6 favoured for JS output (Rails 7 choose a new path again, I'm sorry).
Also, as components typically have actions attached, I don't really see how a mixed Rails (static HTML) based approach could work.
A few ideas:
In the end, both Rails/ERB and React create HTML. Perhaps you can simply create the same HTML that your ShareButton creates with Rails as a temporary workaround? You'd share the CSS from the new front-end project, and you can slowly migrate rebuilding components in React (when you're thinking of building component library, make sure it works with stand alone HTML/CSS).
You can load static HTML in React using dangerouslysetinnerhtml; that might be a solution if you have complex prerendered text you want to load within a React component.
Load React client side (relatively slow); wouldn't really do this for production: How to perform import/export in client-side React JSX using Babel-Standalone
Do some parsing of the HTML received in React; and render components conditionally (this approach is a bit how Rails Turbo works; a more Rails-native answer to React, Vue and the like)
Push through: none of the 'solutions' above are really satisfying if you want to end up with a clean React version.
Roll back: why use react in the first place. React is just another fancy way of rendering HTML.

Implement SSR with React 18 (pipeToNodeWritable) + react redux

As you know the react 18 alpha version which was just released includes :
Suspense and lazy on the server: You can now use and lazy
on the server. Together with the new pipeToNodeWritable method, this
solves long-standing pain points and performance problems with server
rendering:
Code splitting works together with SSR. You don't have to choose one
or the other. React uses your boundaries to stream the page
HTML in visual chunks. React uses your boundaries to
hydrate the page in chunks, improving responsiveness.
More details there : https://github.com/reactwg/react-18/discussions/47
Dan Abramov has developed a demo https://codesandbox.io/s/festive-star-9hfqt?file=/server/render.js
showing how we can set up SSR with react using pipeToNodeWritable, though it is said
we don't have a recommendation yet for how to transfer data from the
server to the client to prepopulate the cache
In a typical SSR app in react/react router, you find the route matching the request, and then you await on all the promises that are within your routes's components.
If you you use redux, you can then set the data into the store and render the html.
Something like that : https://github.com/ilkeraltin/react-ssr-news/blob/master/src/index.js#L42
My question is how would that fit into Dan Abramov's demo ?
In the render.js file there's a createServerData () function, would that be the location where we basically do, what I described above ? (await on route's promises)

Migrating From Ember to React Page by Page Exploring Options

I want to move a big Ember v1.4.0 app to React. Instead of creating a new UI from scratch. I want to start building it in React my converting pages over slowly, essentially mixing React and Ember pages in one website.
Goal:
The above is my ultimate goal, but my first goal is is to create a single page in React that is called by Ember's router.
What I have tried so far: I wanted to create a React component in a ./templates/myFirstTestPage.handlebars because, as I understand it, the router.js calls a template file. But I am unsuccessful creating a React component in the handlebars file. Firstly, I cannot use <script> to import React because <script> does not work in handlebars. Secondly, I believe the handlebars is parsing the React app in an incorrect way. Actually, I don't really understand how, and in what order, these frameworks do the rendering.
Possible solutions (but I need implementation details):
Somehow create a React component in the template folder with the .handlebars extension.
Refer to the url of a React app in the handlebars of an Ember app
Have the Ember router map the url to a jsx file. This solution seems really viable to me. I think to myself that surely the creators of Ember must have thought that people might want to have their Ember app refer to some regular html file. Hence, I hope someone might have some knowledge whether this is possible or not.
Somehow create my own router that maps urls to particular files. If its a React component, then I'd map it to my jsx file, if not, I let Ember's router take care of the mapping. I don't really know how to implement a url mapping thing though.

Server side rendering with devextreme and material ui #react16

After refreshing the page (and going through my ssr) it looks like none of the css is sustained unless I navigate through my app and get back to it Or even click some elements. Are there any examples of how this is done correctly?
Im using the exact same code from the controlled 'react material ui grid' example:
https://github.com/kkotwal94/DrivingService (develop branch) <- where the component is under components / demoBase, and the SSR is under server/render/pageRender.jsx. I use the material ui example for how this is done. I utilize demo grid in Students.jsx.
Here is a pic of what happens post refresh:
Everything else renders fine (all other pages) in production mode and dev mode. I have no clue what im missing here. It looks like the jss-in-css is mapping incorrectly.
I found that reverting back to pre-React 16 everything began to work again SSR and what not, however i cant use dx-react-grid project since it requires 16. Kind of in a wackamole, still investigating where i goofed.
TEST
http://transportation.kkotwal.me/
I hosted it, if you click on login you can log in with yea#yea.com, password: 123, or you can just sign up where the username has to be a email it doesnt matter. After wards if you navigate to the students button on the navigation (if you click on transportation tracker after logging in you should be back to the root page / view). You will see the dev extreme controlled grid example.
If you hit refresh on that page you will see all the css is messed up. In case you arent sure what the page is: http://transportation.kkotwal.me/students. The source is here: https://github.com/kkotwal94/DrivingService/tree/UpdateReact . The server side rendering is located https://github.com/kkotwal94/DrivingService/tree/UpdateReact/server/render. The component for the devExtreme component is called DemoBase.jsx in the components folder, and the container that renders this is https://github.com/kkotwal94/DrivingService/blob/UpdateReact/app/containers/students/Students.jsx.
I guess you're already aware that React 16 came with lots of improvements to server-side rendering. The update came with additional server-side render methods like renderToNodeStream().
The official guide on upgrading React from 15 to 16 mentions that it should have no issues, with minor exceptions. One of those exceptions is a break change exactly when you hydrate a server-rendered container:
Hydrating a server-rendered container now has an explicit API. If you’re reviving server-rendered HTML, use ReactDOM.hydrate instead of ReactDOM.render. Keep using ReactDOM.render if you’re just doing client-side rendering.
Having that in mind, I'd search in your project (and possibly in third-party libraries as well) for some ReactDOM.render that was missed to be changed to ReactDOM.hydrate while upgrading React to version 16.
this is probably the issue at server side code and your nodejs script.
Reason #1:
if you are using material ui version 4.x then you should look at their ssr documentation
in material ui version 3.x or below that we use
JssProvider from 'react jss/lib/JssProvider';
however this is no more required, your both github links are broken , kindly check ssr code of yours and compare it with material-ui documentation
Reason #2:
you have to refer to your build folder for your expressjs
app.use(express.static(path.join(__dirname, '../../build')));
app.use(express.static(path.join(__dirname, 'public')));
this could be another reason and if this is missing then check that your componentDidMount also will not be invoked, so client side rendering won't be happening, however for ssr both client side and server side rendering has to happen
For complete code on SSR kindly refer this link

Prevent mounting/initial rendering of a server rendered react component

I'm using a custom tool similar to react-snap to create a snapshot of my app at build time, as recommended in the create-react-app docs. This generates a static server-rendered version, which I can deploy behind nginx without running react on the server. This works fine.
I'm also using code-splitting to lazily load some components to reduce the initial JS payload. (I use react-loadable, but I'm willing to change that if needed.) It works fine when creating the snapshot, and the HTML is generated correctly, which the user receives correctly, and everything is displayed fully server-rendered without even downloading any JS yet. This is great.
However, during rehydration on the client, the import(...) call for the async loaded component hasn't yet been fired. Meanwhile, the DOM already has the stuff that has to be rendered, from the snapshot.
In this scenario, is there a way to prevent the initial render of a component during mounting, since I already have the content in the DOM?
Also, is it possible to have react's hydration logic run after the import is complete, so that I can prevent any flicker even after the import is complete?
If it matters, the lazy-loaded components are infrequently used routes, managed by react-router.

Resources