I need to send an email of my rendered reactjs component, for that, I need to convert my react component in HTML and send the email. I know how to send HTML through the mail, but getting stuck in how to get HTML from the reactjs component.
You can use renderToString of react-dom/server and use it like
import ReactDOMServer from 'react-dom/server'
const htmlString = ReactDOMServer.renderToString(<App />)
ReactDOMServer is used for SSR (Server Side Rendering) of react components.
renderToString converts your React component to string. So, You will get string html from JSX of your component.
There are two ways to do that. One is the renderToString() method, as the other answer mentions.
The other one is renderToStaticMarkup(): https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup
From docs:
Similar to renderToString, except this doesn’t create extra DOM attributes that React uses internally, such as data-reactroot. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save some bytes.
If you plan to use React on the client to make the markup interactive, do not use this method. Instead, use renderToString on the server and ReactDOM.hydrate() on the client.
For sending email you don't need extra DOM attributes or hydration since the email doesn't include any JS code, renderToStaticMarkup() will do the job.
To get HTML from a react component, you can use theReactDOMServer.renderToString method (doc) used mainly for SSR purpose. However I guess you can achieve what you want with it.
Related
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.
I was trying to understand what's the difference between ReactDOMServer.renderToString() and ReactDOMServer.renderToStaticMarkup() on React 16.8.6.
This is what I understood:
renderToStaticMarkup() is used on the server side when you just want to render the markup and don't want to hydrate it on the client side. (https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup)
renderToString() is used on the server side when you want to use the ReactDOM.hydrate() function to hydrate the application on the client side. (https://reactjs.org/docs/react-dom-server.html#rendertostring)
So, if I'm right, the only difference between this two methods is that renderToString() adds the data-reactroot on the main element of the application. React reinforces this on the renderToStaticMarkup() documentation:
Similar to renderToString, except this doesn’t create extra DOM
attributes that React uses internally, such as data-reactroot. This is
useful if you want to use React as a simple static page generator, as
stripping away the extra attributes can save some bytes.
If you plan to use React on the client to make the markup interactive,
do not use this method. Instead, use renderToString on the server and
ReactDOM.hydrate() on the client.
But, I was reading this issue on React's repository where Dan Abramov said:
Instead, use hydrate() to explicitly tell React to hydrate existing
HTML. Then it won't depend on whether data-reactroot exists or not.
And:
...The suggested migration path is to use ReactDOM.hydrate() which
completely sidesteps the problem because it doesn't rely on the
data-reactroot attribute.
So, my question is: Is data-reactroot relevant to the hydrate function in React or is the documentation wrong?
Understanding this will be really helpful to fix a bug I'm having while hydration.
I want to use react as a js library injected into my html page. like JQuery, to access DOM and manipulate it. In Vue.js we can do this but in react I doubt it works. I can't access DOM out of react Component and render method.I want a solution to access elements out of render method
You can make use of ref callback to access the dom element in react, which is what React Docs recommend to follow..
DOCS
You can use plain native JavaScript, for eg. document.querySelector() in any lifecycle function of React as well as in render().
Can you give an example of what you're trying to do exactly?
What is the best view engine/ method to pre-render a react component on an express backend? I'm at a loss at finding the most appropriate way to do it, all I can find in regards to resources are a bunch of article-tutorials, but they all do it in a different way, so I'm wondering if there is a recommended convention.
Essentially I just want to show 1 component with a bunch of pre-set props. No navigation or anything, just for 1 endpoint. I.e. You go to /component and it returns <Component prop1={1}/>
Just use the renderToString or renderToStaticMarkup methods if you just want the single component rendered and then send it in your response.
See: ReactDOMServer
How can i make my webapp render server-side and send only ready-to-use html to the client, if the client didn't download main.js file yet?
On the server, use React.renderToString (https://facebook.github.io/react/docs/top-level-api.html#react.rendertostring) with the same component JSX and the same props. Then, in your server-rendered template, place the generated string of markup in the same container element where you mount your React component client-side.
React components will generate the same markup in the browser and on the server given the same props. React in the browser is smart enough (via the value of the data-react-id attribute) to recognize that a component has been already rendered to a string on the server and delivered to the browser within the initial page load. So, it won't render it again—it will just hook up the component's events.
If your HTTP server isn't Node-based, you can use a simple messaging implementation (e.g. ZeroMQ or Redis pub/sub) to send rendering requests to a tiny Node script running on the same server. This script should have filesystem access to the same JSX components that you use client-side. The Node script should accept the path to the component JSX and a props object, and return the output of React.renderToString to your main HTTP server for inclusion in a template.