user-defined component in React - javascript

Why does 'element' define what looks like an HTML tag that call's a function.
Why would i not set element to something like: Welcome('Sara')
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);

The format resembling HTML is called JSX:
it is a syntax extension to JavaScript. We recommend using it with
React to describe what the UI should look like
Technically (in this simple case) you could replace the JSX with Welcome({ name: 'Sara' }), but that is not the standard way to render components in React - and it has some technical implications because it is not the same as using JSX (which calls React.createElement).

Related

ReactJS: ReactDOM.Render() in a Variable?

I can't really find any documentation for this but is it possible to put ReactDOM.Render() in its own render/function variable?
The reason for this is I want to stream line my codebase and when trying to render multiple components with props etc it gets a little messy.
Example:
ReactDOM.render(
<SuccessErrorModal status={props.status} progress={50} />,
document.getElementById("loading-modal")
);
Desired Result:
const LoadingModal = (props) => {
ReactDOM.render(
<SuccessErrorModal status={props.status} progress={50} />,
document.getElementById("loading-modal")
);
}
<LoadingModal status={true} /> // Calling the ReactDOM.Render()
Create Portal Example (Not working):
const LoadingModal2 = () => {
ReactDOM.createPortal(
<SuccessErrorModal status={true} progress={50} />,
document.getElementById("loading-modal")
);
};
TIA
You can use ReactDOM.createPortal for this.
Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
You can get more information here

How to convert props.children to string in react js

I want to convert react children to string.
In the below example I am passing div, h2 and p as children to Example in Exampleclass. when I call props.children in Example it returns an array but I need a props.children in the string format so that I can use it in dangerouslySetInnerHTML.
import React, { Component } from "react";
import Example from "./example";
export default class Exampleclass extends Component {
render() {
return (
<div>
<p>in class</p>
<Example> // passing div, h2 and p as children to Example
<div>
<h2>function</h2>
<p>function</p>
</div>
</Example>
</div>
);
}
}
import React from "react";
export default function example(props) {
console.log("child", props.children); // returns array but i need <div><h2>function</h2><p>function</p></div> here
return <div dangerouslySetInnerHTML={{ __html: `${props.children}` }} />; // returns [object Object]
}
It would be difficult to transform children object into some kind of a flat string with a JSX-a-like structure. children is a complex object with a lot of nested fields. You would have to convert it firstly to an array, then iterate over it, probably recursively, pick correct props and so on.
However you could pass your children not as a children, but as a separate prop.
const Child = ({ child }) => {
return <div dangerouslySetInnerHTML={{ __html: child }} />;
};
const App = () => {
const data = `
<div>
<h2>function</h2>
<p>function</p>
</div>
`;
return <Child child={data} />
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
Edit: You could, however, use renderToStaticMarkup function, but it will render only pure html (it will compile components into html). In your example you are passing only html elements so I guess it would be okey.
const markup = ReactDOMServer.renderToStaticMarkup(children);
return <div dangerouslySetInnerHTML={{ __html: markup }} />;
react-children-utilities has a function, onlyText, that does this.
It uses React.Children.toArray(children).reduce then recursively loops through children, concatenating a string made up of every child and nested child that is a string or a number, skipping everything else.
Disclaimer: be aware that if your component's children includes components with props or attributes that behave like children when rendered, but aren't actually in the React elements as children, they'll be omitted.
For example, if you're trying to approximate the text that tools like screen readers or search engine bots would read on focusing an element, this approach will skip text in attributes like alt, label or value that such tools might include. It also won't do things like collapse whitespace.
Since onlyText is a pretty simple function, I'd suggest looking at its implementation (linked above) and consider writing your own variant that adds in any other relevant attributes that your use case needs which would otherwise be skipped.

reactjs : Diffrence between regular/arrow functions and react functional components

What difference you see between regular/arrow functions and react functional component
React functional component
import React from 'react';
function MyComp(){
return <span>test</span>
}
Regular function
function myFun(){
return null;
}
Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called props) and return React elements describing what should appear on the screen.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
From a JavaScript perspective, this is nothing but a function, except for a special return. It's JSX and each JSX element is just syntactic sugar for calling React.createElement(component, props, ...children).
Basically, you can replace the JSX in the example above with something like:
React.createElement('h1', null, `Hello ${props.name}`);
And this is nothing but a JavaScript :)
And then you can render your component:
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
You call ReactDOM.render() with the <Welcome name="Sara" /> element.
React calls the Welcome component with {name: 'Sara'} as the props.
Our Welcome component returns a <h1>Hello, Sara</h1> element as the result.
React DOM efficiently updates the DOM to match <h1>Hello, Sara</h1> and you get it on the screen.
There is one important requirement for React functional component!
Always start component names with a capital letter.
React treats components starting with lowercase letters as DOM tags. For example, represents an HTML div tag, but represents a component and requires Welcome to be in scope.
This function from your example can be used as a functional component:
function MyFun() { // name should start with a capital
return null;
}
React won't display anything because React does not render if component returns null.

how does the .render() function in react work internally?

I can define a component like this:
class Welcome extends React.Component {
render() {
return <h1>Hello!</h1>;
}
}
When I want to render this object in the Dom (or rather add it to the virtual DOM) I call
ReactDOM.render(
<Welcome />,
document.getElementById('root')
);
That means that at some point multiple .render() functions are nested inside of each other since we defined return <h1>Hello!</h1>; inside of the .render() function of Welcome.
It also means that I can use the .render() method to render an Object to the DOM and to define a new react object.
This syntax is from the official documentation
Does .render() just render things to the virtual DOM and the nesting is resolved by React internally or is there more behind it?
From Rendering a Component:
(updated to reflect your code)
class Welcome extends React.Component {
render() {
return <h1>Hello!</h1>;
}
}
ReactDOM.render(
<Welcome />,
document.getElementById('root')
);
We call ReactDOM.render() with the <Welcome /> element.
React calls the Welcome component with {} as the props.
Our Welcome component returns a <h1>Hello!</h1> element as the result.
React DOM efficiently updates the DOM to match <h1>Hello</h1>.
It may be beneficial to read up on the React Life Cycle.
To understand render you have to understand how react works internally. To understand this in greater detail I would recoment reading this but here is a quick overview:
Conceptually a react component is a just a function that returns an Object like this:
{
type: 'button',
props: {...}
};
So the render() part of a class component just specifies what part of the component will be returned. The react virtual dom is made up of many of these object nested inside of each other (in props.children). React will start at the top object, turn it into an html node and render it to the dom, then do the same for all of its children etc.

Making an HTML string from a React component in background, how to use the string by dangerouslySetInnerHTML in another React component

I'm trying to render LaTeX strings in a React project.
Although I use the react-mathjax React components, I want to get an HTML string made from the LaTeX strings in order to concatenate it and the other strings and set it by dangerouslySetInnerHTML.
My current code I tried
Sample cod here
LaTeX strings are given as strings
Make an empty DOM aDom by document.createElement('span') (in background. not in the document DOM tree.)
Render a LaTeX string by ReactDOM.render into aDom
After rendering, get a string by aDom.innerHTML or .outerHTML
Problem
The value of aDom.innerHTML (or .outerHTML) is "<span><span data-reactroot=\"\"></span></span>" (almost empty)
although aDom has a perfect tree that MathJax generated.
Briefly,
aDom: 🙆
aDom.outerHTML: 🙅
Question
How can I get the 'correct' HTML string from aDom above?
This seems to work just fine if you want to render any component to a HTML string:
import { renderToStaticMarkup } from 'react-dom/server'
function componentToString() {
return renderToStaticMarkup(<MyAwesomeComponent some="props" or="whatever" />)
}
From what I see, you are getting what you'd expect to get.
Given a root element (aDom in your case), ReactDOM will render it's root component inside this element, and this component's element will have the attribute data-reactroot.
So what you are seeing is exactly how it should be. From what I've tested, the inner dom tree should be there as well.
var Another = React.createClass({
render: function() {
return (
<div>Just to see if other components are rendered as well</div>
);
}
});
var Hello = React.createClass({
render: function() {
return (
<div id="first">
<div id="sec-1">Hello</div>
<div id="sec-2">{ this.props.name }</div>
<Another />
</div>
);
}
});
var a = document.createElement('div');
ReactDOM.render(
<Hello name = "World" /> ,
a
);
console.log(a.outerHTML);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
The result in the console is:
<div><div data-reactroot="" id="first"><div id="sec-1">Hello</div><div id="sec-2">World</div><div>Just to see if other components are rendered as well</div></div></div>
I recommend using renderToStaticMarkup over renderToString as it does not add any extra DOM attributes that React uses internally, like `data-reactroot:
import { renderToStaticMarkup } from 'react-dom/server'
getString() {
return renderToStaticMarkup(<AnyComponent />)
}
Documentation:

Categories