components in react are imported but not visible when used [duplicate] - reactjs

I am playing around with the ReactJS framework on JSBin.
I have noticed that if my component name starts with a lowercase letter it does not work.
For instance the following does not render:
var fml = React.createClass({
render: function () {
return <a href='google.com'>Go</a>
}
});
React.render(<fml />, document.body);
But as soon as I replace the fml with Fml it does render.
Is there a reason I cannot begin tags with small letters?

In JSX, lower-case tag names are considered to be HTML tags. However, lower-case tag names with a dot (property accessor) aren't.
See HTML tags vs React Components.
<component /> compiles to React.createElement('component') (html tag)
<Component /> compiles to React.createElement(Component)
<obj.component /> compiles to React.createElement(obj.component)

#Alexandre Kirszenberg gave a very good answer, just wanted to add another detail.
React used to contain a whitelist of well-known element names like div etc, which it used to differentiate between DOM elements and React components.
But because maintaining that list isn't all that fun, and because web components makes it possible to create custom elements, they made it a rule that all React components must start with a upper case letter, or contain a dot.

From the official React reference:
When an element type starts with a lowercase letter, it refers to a built-in component like or and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
Also note that:
We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.
Which means one has to use:
const Foo = foo; before using foo as a Component element in JSX.

The first part of a JSX tag determines the type of the React element, basically there is some convention Capitalized, lowercase, dot-notation.
Capitalized and dot-notation types indicate that the JSX tag is referring to a React component,
so if you use the JSX <Foo /> compile to React.createElement(Foo) OR <foo.bar /> compile to React.createElement(foo.bar) and correspond to a component defined or imported in your JavaScript file.
While the lowercase type indicate to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement('div').
React recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter,
assign it to a capitalized variable before using it in JSX.

In JSX, React Classes are capitalized to make XML compatible, so that it is not mistaken for an HTML tag. If the react classes are not capitalized, it is an HTML tag as pre-defined JSX syntax.

User define components must be Capitalized
When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
React recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.
For example, this code will not run as expected:
import React from 'react';
// Wrong! This is a component and should have been capitalized:
function hello(props) {
// Correct! This use of <div> is legitimate because div is a valid HTML tag:
return <div>Hello {props.toWhat}</div>;
}
function HelloWorld() {
// Wrong! React thinks <hello /> is an HTML tag because it's not capitalized:
return <hello toWhat="World" />;
}
To fix this, we will rename hello to Hello and use <Hello /> when
referring to it:
import React from 'react';
// Correct! This is a component and should be capitalized:
function Hello(props) {
// Correct! This use of <div> is legitimate because div is a valid HTML tag:
return <div>Hello {props.toWhat}</div>;
}
function HelloWorld() {
// Correct! React knows <Hello /> is a component because it's capitalized.
return <Hello toWhat="World" />;
}
Here is the reference

Related

findByText over multiple components

I'm looking to do some testing on some components. However, it fails given that some components are nested, but I want to simply check if the text is rendered on the screen.
For example:
<div>Hello <br />World</div>
<div>Hello <p>World</p></div>
<p>Hello</p><p> World</p>
I'm not looking to see if they're rendered inside the correct components, but to see if the text "Hello World" is rendered at all.
From what I'm seeing in my testing, it is not.
You will need to inspect the textContent property of the HTML node, which includes all inner text as a string.
With JS:
const component = render(...)
expect(component.container.innerContent).toContain(...)
With Jest extend-expect:
const component = render(...)
expect(component.container).toHaveTextContent(...)

"Introduce Prop" refactoring in WebStorm for React for functional components

In WebStorm and JetBrains IDEs there's a very handy refactoring tool named "Introduce Parameter" which takes the selected text and converts it to a parameter and replaces any calls to the function with the original selection as a parameter. It is available by selecting an expression inside a function, right clicking, Refactor > Introduce Parameter or through shortcut Ctrl Alt P.
For React functional components, parameters are passed as props which is a JavaScript object that contains all attributes passed to the JSX tag.
Is there a similar refactoring action available to introducing a prop to a functional component?
Example:
Before:
function ChildComponent() {
return <div>Hello World</div>
}
function ParentComponent() {
return <div>
<ChildComponent/>
</div>
}
User selects Hello World in editor and uses shortcut for hypothetical Introduce Prop action
After:
function ChildComponent(props: { helloWorld: string }) {
return <div>{props.helloWorld}</div>
}
function ParentComponent() {
return <div>
<ChildComponent helloWorld={"Hello World"}/>
</div>
}
If a whole tag block is selected instead of a string the type of introduced prop would be JSX.Element.
If this functionality is not available natively through WebStorm, is there functionality to add the refactoring customly or perhaps is there a plugin for it?

REACT how come when we create a function called "App" the return html runs but doesn't work if any other? [duplicate]

I am playing around with the ReactJS framework on JSBin.
I have noticed that if my component name starts with a lowercase letter it does not work.
For instance the following does not render:
var fml = React.createClass({
render: function () {
return <a href='google.com'>Go</a>
}
});
React.render(<fml />, document.body);
But as soon as I replace the fml with Fml it does render.
Is there a reason I cannot begin tags with small letters?
In JSX, lower-case tag names are considered to be HTML tags. However, lower-case tag names with a dot (property accessor) aren't.
See HTML tags vs React Components.
<component /> compiles to React.createElement('component') (html tag)
<Component /> compiles to React.createElement(Component)
<obj.component /> compiles to React.createElement(obj.component)
#Alexandre Kirszenberg gave a very good answer, just wanted to add another detail.
React used to contain a whitelist of well-known element names like div etc, which it used to differentiate between DOM elements and React components.
But because maintaining that list isn't all that fun, and because web components makes it possible to create custom elements, they made it a rule that all React components must start with a upper case letter, or contain a dot.
From the official React reference:
When an element type starts with a lowercase letter, it refers to a built-in component like or and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
Also note that:
We recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.
Which means one has to use:
const Foo = foo; before using foo as a Component element in JSX.
The first part of a JSX tag determines the type of the React element, basically there is some convention Capitalized, lowercase, dot-notation.
Capitalized and dot-notation types indicate that the JSX tag is referring to a React component,
so if you use the JSX <Foo /> compile to React.createElement(Foo) OR <foo.bar /> compile to React.createElement(foo.bar) and correspond to a component defined or imported in your JavaScript file.
While the lowercase type indicate to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement('div').
React recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter,
assign it to a capitalized variable before using it in JSX.
In JSX, React Classes are capitalized to make XML compatible, so that it is not mistaken for an HTML tag. If the react classes are not capitalized, it is an HTML tag as pre-defined JSX syntax.
User define components must be Capitalized
When an element type starts with a lowercase letter, it refers to a built-in component like <div> or <span> and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like <Foo /> compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.
React recommend naming components with a capital letter. If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.
For example, this code will not run as expected:
import React from 'react';
// Wrong! This is a component and should have been capitalized:
function hello(props) {
// Correct! This use of <div> is legitimate because div is a valid HTML tag:
return <div>Hello {props.toWhat}</div>;
}
function HelloWorld() {
// Wrong! React thinks <hello /> is an HTML tag because it's not capitalized:
return <hello toWhat="World" />;
}
To fix this, we will rename hello to Hello and use <Hello /> when
referring to it:
import React from 'react';
// Correct! This is a component and should be capitalized:
function Hello(props) {
// Correct! This use of <div> is legitimate because div is a valid HTML tag:
return <div>Hello {props.toWhat}</div>;
}
function HelloWorld() {
// Correct! React knows <Hello /> is a component because it's capitalized.
return <Hello toWhat="World" />;
}
Here is the reference

Protect against React Instances

I'll keep it short. Using Typescript 2.7.2 and ""#types/react": "^16.0.40","
Having really bad problems trying to protect against React Component instances.
consider the component
IFooProps {
element: SomeType
}
...component<IFooProps> {
....
render() {
return (
react.cloneElement(element, {onClick: this.myOnClickHandler});
)
}
}
If element is a react component instance the onClick will be applied to the instance and not run ever. However if its a valid element type I.E div, input, span etc the onClick will get cloned onto the element and run fine.
what type do i replace "SomeType" with to allow JSX elements like div, span, input etc... but not Component instances.
<Foo element={<Bar/>} should fail typecheck
<Foo element{<div/>} should pass typecheck
iv'e tried ReactNode, ReactElement, ReactHTML, JSX.Element, etc etc etc nothing seems to properally type check it.

React - pass props/state to rendered HTML string?

In my React app, I have stored a text template as an HTML string on the server which is passed up to the client to be rendered. Is it possible to render this HTML string in such a way that it can access it's parent component state/props? I've tried using dangerouslySetInnerHTML and ReactDOMServer.renderToString(), both of which render the string as HTML, but render {props.text} as a literal string, rather than a reference to the component's props.
For example, on the server I have stored:
<div>Welcome to my app</div>
<div>{props.message}</div>
<div>Have fun</div>
And the component
import React from "react"
import { connect } from "react-redux"
const mapStateToProps = (state) => {
return { state }
},
WelomeBody = (props) => {
return (
<div dangerouslySetInnerHTML={{"__html": props.state.welcomeMessageBody}} />
)
}
export default connect(mapStateToProps, null)(WelomeBody)
but this results in:
Welcome to my app
{props.message}
Have fun
Is there a way that this can be rendered so as to access the value of props.message, rather than just rendering it literally?
If what you have in mind is to send down a React component (in JSX syntax) from your server to your client and have the client somehow rehydrate/compile it into an actual, working component, this is not achievable that easily.
When you build and bundle your React app, only components that are statically referenced/imported in your application at compile time can be used at runtime on the browser.
So, in order to dynamically render a component from a template and embed variables into it, your choices are:
Render it into final HTML on your server, send down that HTML and have a simple React component perform dangerouslySetInnerHTML for it. But, like you've already observed, that content has to be the full HTML code, no templates, variables, JSX, etc. Everything is string and HTML at this point, no more processing.
Alternatively, send down a Markdown document and have a Markdown component parse it into HTML and display it.
Create a sophisticated component that can receive a string, parse it, tokenize it, substitute values in it, etc. Essentially, create your own template-processing component that can read a template (the string sent down from your server) and embed the appropriate values into it.
A simple solution (to substitute values into a template) would be:
function Filler(props) {
let html = props.template;
Object.keys(props).forEach(key => {
if (key !== "template")
html = html.replace("{" + key + "}", props[key]);
});
return <div dangerouslySetInnerHTML={{__html: html}} />;
}
and use it like
<Filler template={"<h1>Hello, {firstname} {lastname}</h1>"} firstname="John" lastname="Doe" />
But again, this is far from a full-fledged actual React component.

Resources