Dynamically rendering React component within HTML - reactjs

In my React app, there's a module that renders HTML. I created the following little function in the component that renders the HTML.
renderContent(content) {
return { __html: content }
}
And here's how I call it:
<div className="padding-20" dangerouslySetInnerHTML={this.renderContent(this.props.myContent)}></div>
This has worked so far because the section within the component where I needed to render HTML was separated within a particular <div>.
Now, I'd like to render a component, specifically a <form> within this HTML section and the form itself is in a separate component. Trying to figure out how I can do this.
I think I could set an id to a <div> or use specific class that indicates the existence of a component and somehow render the component there. Has anyone tackled this before? If so, I'd appreciate some suggestions.

The answer depends on a few variables. Some Points of clarification with answers depending on your needs.
This form is a React component? Or is it raw HTML?
Ir exists to in ComponentA and you’d like to render it in ComponentB?
React Portals are the solution designed for this exact problem. They allow you to render content from one component to anywhere else in the DOM.
If you use a portal, I don’t believe passing raw HTML will work. Instead, pass as the first argument a div setting your form using dangerouslySetInnerHtml.

Related

React render component withtout breaking tree when using other libraries

Some situation
I am currently using the js library code-mirror (v5) (a text editor with some nice features, such as syntax highlighting) and i must add widgets to it using its API.
It is quite straightforward, you just give code-mirror's API the html element you created for the occasion and it will add it to the page document inside the dom it generated for the editor.
So i just mount a new react component on the HTML element i fed to the code-mirror API. It is correctly rendered without errors, but...
The Problem
While the method above works I'm quite sure that's not the way to do it for multiple reasons.
The created component lose the parent context (so change to props doesn't update the created component & stores such as redux are inaccessible)
It breaks from the app react tree
It is not cleaned up with the destruction of any component and will just remain in memory until we use ReactDOM.unmountAtNode()
I tried stuff with portals but it doesn't seems to be what i need in this case (if i got it right portals do render things outside of the react tree)
Example
This an example of a method that would add a react component to the codemirror as a widget
function addWidget(component: ReactElement, position: Position): void {
const div = document.createElement('div');
ReactDOM.render(component, div);
//code mirror api
editor.addWidget(position, div, false);
}
Conclusion
I am looking for React best practices in these cases where components needs to be mounted on dynamically created HTML element without losing context and still being attached to some part of the app react tree.
Thank for your time.

How to use existing HTML element in React?

Is it possible to reference existing HTML element in React?
I have a page where React used only for small part of components and I have "video" element that exists on page before React loads. Then I have a react component which have a couple of props that should affect video element.
What is the best/correct way to achieve this?
Currently, in render method of a component, I use document.getElementById('video-' + this.props.videoId) and then manipulating it. I thought that I can somehow use "refs" to say to reuse the existing HTML element, but not sure how and didn't found useful information.
Thanks!
What I understand is, you have an app, probably built in some other stack and you are trying to use React inside that app. The page is loaded before and then the React component renders. As pointed out by Icepickel, refs are for the components that are created by you inside the React app. So, you can't use that here.
Normally, it is discouraged to directly access the elements in the DOM. But since you are using it on a part of it, so it is totally fine. But doing it in the render() method is not the right choice here.
Instead what you can do is, utilize the React lifecycle methods to control the video player in a better way. Normally when a component is mounted on the DOM. Following lifecycle methods are called in the following order:
constructor
componentWillMount
render
componentDidMount
So, what I will suggest is, inside the constructor set the state using document.getElementById('video-' + this.props.videoId). [I am assuming the page laods before the react component].
let el = document.getElementById('video-' + this.props.videoId);
this.state = {
videoPlayer: el;
}
And then later when your component is mounted. Inside the componentDidMount, change whatever you want to change in the video player.
I have also created a small Code Sandbox Sample to elaborate on the lifecycle methods. This way, you will be able to write cleaner code and easily manage the state of the video player.

React props vs children. What to use when?

What is the difference between the two approaches ?
Passing text for a button as props
<TextComponent title="Save"/>
function TextComponent(props){
return <button>{props.title}<button/>
}
vs
Passing text as a child
<TextComponent>Save<TextComponent />
function TextComponent(props){
return <button>{props.children}<button/>
}
children prop is something that you use when the structure of what needs to be rendered within the child component is not fixed and is controlled by the component which renders it.
However if behaviour of the component is consistent across all its renders it can define the specific props that it needs and the parent can pass them to it.
A very simple example could be a Navbar which can use children. For a Navbar the items that it needs to render as well as the order or alignment or items depends on how it needs to be used at different instances or across different pages. For instance Navbar somewhere can have Search component at one place and at some other place not have it. Also the menus may sometimes be needed to the left followed by Login menu item to the right and a searchbar between them and sometimes they may all be present to the right without the searchbar. In such cases the parent component can control how the internal structure would be
You should use children when you don't know them ahead of time, see: https://reactjs.org/docs/composition-vs-inheritance.html
Here, if you KNOW that you'll use a title inside your child component, just use a named prop.
I'd say that if you ask yourself the question: "Ok, but what will that generic component render?" is when you should use children
You use props.children on a component which acts as a container and does not know about their children ahead of time.
Basically props.children it is used to display whatever you include between the opening and closing tags of the "containing" component when invoking it.
As mentioned in the React official docs:
Some components don’t know their children ahead of time. This is especially common for components like Sidebar or Dialog that represent generic “boxes”.
We recommend that such components use the special children prop to pass children elements directly into their output:
Simply put, it props.children just displays whatever is put between the opening and closing tags.
As asked in your question, there is not much difference in the use case specified by you.
But, say you had a small left icon the component then passing 'title' as a separate prop would make more sense Eg.
<TextComponent title="Save" src="https://..." />
function TextComponent(props) {
return (
<div>
<img src={props.src}/>
<button>{props.title}<button/>
</div>
);
}
When you do know what your props are, use props. Otherwise, use children (aka containment).
Other than that, using props/children in your case depends on what you want to pass:
If its a single props (like item), than it doesn't matter which method you'll choose.
Else, you should check what you are passing inside children as you might pass other values which you don't want to render.
I would suggest using the selective approach (e.g props.title), since you are always aware of whats going inside your components.

Generically adding custom properties to components

I am new to reactjs. I am trying to generically add custom properties to react components. Here is my use case ...
For a react component called HelloWorld, I want the DOM to show the attribute data-js-class="HelloWorld". The reason I want to do this is because when I am inspecting the DOM in dev tools, I can quickly identify the component that rendered that piece of the DOM.
I can do the same thing by going into the React tab of dev tools and jump to the generated DOM element.
I can also do the same in the components render() method by adding properties in every single component. But I dont want to do that in every single component. I want it to happen magically at a framework level.
I have tried to backup the React.createElement and write my own custom createElement which eventually calls the original React.createElement() method. It wasnt an elegant solution.
On the base React.Component class, I added a createElement() (to the React.Component.prototype) method. The component's render method calls "this.createElement(...) instead of "React.createElement()". But this is not elegant either because there is JSX too which this solution will not handle.
class HelloWorld extends React.Component {
render() {
return React.createElement(
'h1',
null, //this.props
'Hello world'
)
}
}
... should render
<h1 data-js-class="HelloWorld">Hello World</h1>
What would be the most elegant way of achieving this?
What would be the most elegant way of achieving this?
I believe adding the metadata for the sake of reviewing which component generated the DOM.
You can simply go to the React devtool and find out which DOM node was generated as shown below.

How to make an easily embeddable React component that displays any other component's state when used as its child?

I'd like to make a React component that, when inserted inside any other component, will display its state in a DIV floated to the right of the screen. Let name it StateExplorer.
Because many StateExplorers can be used on the same page, the DIVs will stack with the same z-index.
The challenge here is to make StateExplorer easily non-verbosely embeddable, like this:
<SomeComponent>
<StateExplorer/>
....
</SomeComponent>
The particular issue here is: how do I hook on componentWillUpdate() so that the StateExplorer always displays up-to-date state? I could use a mixin, but that throws 2 problems:
componentWillUpdate() can be implemented already in the parent component
adding a mixing adds more verbosity; the ideal case is to just add StateExplorer and nothing more.
P.S. I know about React Debug Tools, but it's not so convenient in some cases and adds extra steps before you can see state of a single component.
Sounds like what you need is a Higher-order component.
Here is a good article about it: https://medium.com/#dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750

Resources