How do I render a string as children in a React component? - javascript

Take a simple component:
function MyComponent({ children }) {
return children;
}
This works:
ReactDOM.render(<MyComponent><span>Hello</span></MyComponent>, document.getElementById('stage'));
but this doesn't (I removed the <span/>):
ReactDOM.render(<MyComponent>Hello</MyComponent>, document.getElementById('stage'));
because React tries to call render on the string:
Uncaught TypeError: inst.render is not a function
On the other hand, this works fine:
ReactDOM.render(<p>Hello</p>, document.getElementById('stage'));
How do I make <MyComponent/> behave like <p/>?

If you're using React 16.2 or higher, you can do this using React fragments:
const MyComponent = ({children}) => <>{children}</>
If your editor doesn't support fragment syntax, this will also work:
const MyComponent = ({children}) =>
<React.Fragment>{children}</React.Fragment>
Keep in mind that you're still creating & returning a component (of type MyComponent) as far as React is concerned - it just doesn't create an additional DOM tag. You'll still see a <MyComponent> tag in the React Debug Tools, and MyComponent's return type is still a React element (React.ReactElement).

Well the difference is <p> is an html element and MyComponent is a React Component.
React components need to render/return either a single component or a single html element.
'Hello' is neither.

You need at least one top-level HTML element. Your component can't really just output a string, that's not how React works.
The simplest solution is to simply make your MyComponent wrap it's output in a span or div.
function MyComponent({ children }) {
return <span>{ children }</span>;
}

Currently, in a component's render, you can only return one node; if
you have, say, a list of divs to return, you must wrap your components
within a div, span or any other component.
source
And what you are returning is not a root node. You are returning a react component that is returning a string where it should be returning an HTML element.
You can either pass your string already wrapped with an HTML element (like you already did in your example) or you can wrap your string in a HTML element inside your "MyComponent" like this
function MyComponent({ children }) {
return <span>{ children }</span>;
}

React can render either React components (classes) or HTML Tags (strings). Any HTML tag is by convention lowercase where a Component is Capitalized. Every React component has to render exactly one Tag (or null). To answer your question: you cannot.
In the example above, you render what's given with the children attribute where this will render the tag inside or a string that is not valid.

Related

Why react use angular brackets in rendering the component

I am new to the react as my background is ruby, so maybe it look a silly or noob question.
i come to the article
"Every component must begin with a capital letter. And once a component is declared, it can be written and used very similarly to an HTML element." and also this
"To use this component in your application, use similar syntax as normal HTML: "
class Car extends React.Component {
constructor() {
super();
this.state = {color: "red"};
}
render() {
return <h2>I am a {this.state.color} Car!</h2>;
}
}
root.render(<Car color="red"/>);
we have a car component created using class component so my question here is Why we use angular bracket here for creating instance of Car class. is this a syntax of creating instance of class in react.
Or
To use this component we have to use similar syntax as HTML. why?
React uses angular brackets () in rendering an element as a result it permits you to incorporate the element as a JSX part. JSX may be a syntax extension for JavaScript that permits you to write down HTML-like code in your JavaScript files. it's not obligatory to use JSX with React, however, it's a preferred alternative, as a result, it makes it easier to grasp the structure of your elements and the way they relate to the DOM.
To render an element in React, you'll use the ReactDOM.render() methodology and pass it to the element you wish to render further as a DOM part.
import React from 'react';
import ReactDOM from 'react-dom';
const MyComponent = () => <h1>Hello, World!</h1>;
ReactDOM.render(<MyComponent />, document.getElementById('root'));
The MyComponent operation is wrapped in angular brackets () and passed to the ReactDOM.render() methodology as a JSX part. This tells React to treat the operation as an element and render it within the DOM part with the id of the root.
Hopefully this helps. Before React we needed an index.html File and had to call your javascript.js file within your HTMLenter image description here. example: in HTML, if we wanted to select a Button in javascript and add an onClick event we had to call the button but be specific as possible, so we had to add a class,ID, etc... Import your button to your javascript file like car= document.getElementById("car1")
and then add a onclick event. as you can see this can be exhausting. worst part is you cant add HTML in your Js file, so no tags, etc.. so the way to make things easier in HTML is adding brackets. React allows you to use HTML and Js syntax.
in your example: return I am a {this.state.color} Car!;
we are telling React we have h2 from HTML but anything within { } is Javascript. as you can see React just makes easier to use HTML and javascript in the same file

"Objects are not valid as a React child" when trying to return a Node inside render()

I got the following to show on my page:
export class OverworldComponent extends React.Component<OverworldComponentProps, {}> {
render() {
return <b>Hello, world!</b>
}
}
Instead of Hello, world! though, I would like to output a clone of an HTMLElement already on the page. (A table, to be specific.)
export class OverworldComponent extends React.Component<OverworldComponentProps, {}> {
render() {
return document.querySelector('div.file div.data table').cloneNode(false);
}
}
This compiles but causes the following error (Chrome Inspector):
And it doesn't feel right to just look for ways to "cast" my HTMLTableElement to something React-compatible. When I did try to cast with <HTMLElement>, it was interpreting it as a tag (missing closing tag) instead of casting. So I must not understand what the mechanics is within render(). I think there's something in the framework I should be doing differently, but I don't know what.
For context, I'm in the middle of a hackathon that ends tomorrow, and I began learning React and Typescript today, so I'm missing a lot of knowledge (and lack any experience at all).
document.querySelector('div.file div.data table').cloneNode(false); is pure Web API. This means it returned DOM node, not React Component.
The child of React Component must be also a React Component.
If you want to inject a DOM node into a React Component, consider using dangerouslySetInnerHTML https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
For detail:
dangerouslySetInnerHTML is a prop and its value is an object:
{ __html: '<p>a chunk of html source code</p>' }
In your case, it could be:
{ __html: document.querySelector('div.file div.data table').innerHtml }
or
{ __html: document.querySelector('div.file div.data table').textContent }
You also could use nodeValue, innerText
Read here to see the differences and pick the best one:
nodeValue vs innerHTML and textContent. How to choose?

react dangerouslySetInnerHTML not re-rendering content

Here's my setup:
string-file.properties
someKey=This is my <span class="hello">{0}</span> string!
react-file.jsx
import stringAPI from 'string-file';
class MyComponent extends Component {
get content() {
return { __html: stringAPI.someKey(this.props.word) };
}
render() {
return (
<span dangerouslySetInnerHTML={this.content} />
);
}
}
The argument to stringAPI.someKey get substituted for {0} in the string file and then the final html string is returned. My issue is that this.props.word is being updated while MyComponent is not being updated.
I read somewhere that dangerouslySetInnerHTML tells React that it doesn't need to watch the state of the component that the html is rendered in. If that's true, then I still need a way to do what I'm trying to do.
Set the string as state. When receive new props (componentWillReceiveProps) do a setState. This should rerender the component. If that is not working make sure a unique key is set when the string changes. This also forces a rerender
After adding unique key on div it's working fine.

React Component without Function or Class?

On occasion, I have both seen and wrote some React code like this.
const text = (
<p>
Some text
</p>
);
This does work, but are there any issues with this?
I know I can't use props this way, but if all I'm doing is rendering something simple like a paragraph, I don't see why I would need to make it a functional component or extend React.Component
My current reason for this is because I need to pass in a paragraph or two as placeholder text and I can't just pass in plain text.
This is not a react component, it is just a variable in which JSX is stored:
const text = (
<p>
Some text
</p>
);
As per DOC:
const element = <h1>Hello, world!</h1>;
This funny tag syntax is neither a string nor HTML.
It is called JSX, and it is a syntax extension to JavaScript. We
recommend using it with React to describe what the UI should look
like. JSX may remind you of a template language, but it comes with the
full power of JavaScript.
props will be available only in React component, either in Functional Component or a Class based Component.
Why React is required in this if it is not a react component?
We can store JSX in any variable and it will get transpiled by babel, and get converted into React.createElement.
As per DOC:
JSX just provides syntactic sugar for the React.createElement()
function.
Since JSX compiles into calls to React.createElement, the React
library must also always be in scope from your JSX code.
Example: when we write:
var a = <div> Hello </div>
Result of this will be:
var a = React.createElement(
"div",
null,
" Hello "
);
This code is just storing a paragraph element with the text inside it into the variable text. It's not a component, functional or otherwise. Use it in a React component like you would standard Javascript:
render() {
return (
<div className="some-text">
{ text }
</div>
);
}

ReactJS' Higher Order Components error: "Unknown props"

Yesterday, I was reading the React documentation on higher order components and I was trying to use some of the examples that they have. But, for me, it isn't working.
Here is a simple HOC I created just to wrap another component and see how this works. But since the very beginning, it never worked.
import React, { Component } from 'react';
export default function (enhacedComponent) {
class Authenticate extends Component {
constructor(props) {
super(props);
}
render() {
return <enhacedComponent {...this.props} />;
}
}
return Authenticate;
}
It always returns me this error:
Warning: Unknown props `location`, `params`, `route`, `router`, `routeParams`, `routes` on <enhacedComponent> tag. Remove these props from the element.
When I check the HTML elements part in the console, I find that the actual value this HOC returns is <enhacedComponent></enhacedComponent>. So the wrapped component never got out!
So, in the end, the wrapped component never returns. Just a JSX version of what should be the argument of the HOC.
I think that since JSX is just a another syntax and the unique way to pass plain JavaScript is using {}, I tried to do this, to no success:
<{enhancedComponent} {...this.props }/>
I really don't know what to do or what I am doing wrong.
I'm using this HOC reference. I'm using Webpack 2 with webpack-dev-server as tools on Windows 10.
React thinks you're trying to pass these props to a DOM element and not a react component, which will give you the unknown props error. React interprets lower camel case as a DOM element, so enhacedComponent should be EnhacedComponent.
More info here:
https://facebook.github.io/react/warnings/unknown-prop.html

Categories

Resources