ReactJS component names must begin with capital letters? - javascript

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

Adding template literals to an img src tag

return(<div> <img src = ${coins[0].image}> </div>);
Hi, so I am using react to return an image which is saved in an array that I have called coins. coins[0].length returns a url that I want to use the image of but this is throwing this error.
"JSX value should be either an expression or a quoted JSX text"
It wants me to use quotes, how can i use my array? Thanks
Look at the tutorial:
Specifying Attributes with JSX
You may use quotes to specify string literals as attributes:
const element = <div tabIndex="0"></div>;
You may also use curly braces to embed a JavaScript expression in an
attribute:
const element = <img src={user.avatarUrl}></img>;
You have done neither. (You also forgot the end tag for the <img> component.
Also look at the syntax for template literals: Templates are delimited with backticks, you you left them out.
Thus:
return(<div> <img src={`${coins[0].image}`}></img> </div>);
That said, using a template literal here is probably pointless and you could just use the value directly (unless you need to explicitly coerce it to a string from some other data type):
return(<div> <img src={coins[0].image}></img> </div>);

How can I pass down through props a string of text with a link embedded within?

I have a few sentences to pass down as a prop for a component and I would like the word "here" to include a link so the user can click.
I have tried the plus sign to concat the string, I have tried to use replace (example below)
but I cannot find any solutions.
The "replace" method leaves [object Object] in place of the word here.
Example code:
const textWithoutLink= "First part of the project is on another page. For a
full description you can go here for a full explanation and walkthrough of
the project."
const textWithLink= textWithLink.replace('here', <a href=
'www.page.com'>HERE</a>)
return(
<projectcard
text={textWithLink}
/>
)
Send it as a React fragment rather than as a string:
const fragment = <>
First part of the project is on another page. For a full description you can go here for a full explanation and walkthrough of the project.
</>;
<ProjectCard
text={fragment}
/>
IF for some reason that's impossible (but it really shouldn't be), you could use dangerouslySetInnerHTML in ProjectCard instead, using the string with HTML in it. But it has that name, and is awkward to use, for a reason. :-)
Note that in the above I've assumed that your component is ProjectCard, not projectcard, as the latter being in all lower case would mean React/JSX would assume it was an HTML element, not a React component.

Angular 5 Component Selector in variable returning string instead of component content

I have some data that contains the selector of a component:
{
label: 'This is a label',
componentSelector: '<app-mycomponent></app-mycomponent>'
}
In my app.component.html
Instead of doing this (for example):
<div>
<app-mycomponent></app-mycomponent>
</div>
I would like to do this:
{{data.componentSelector}}
At the moment when I try this it's returning a string instead of replacing it with the contents of the component.
How can I do this?
You cannot interpolate a component, because it is made up of typescript, html, and css. it has to compile to be displayed, if you think about it, it makes sense.
On another note, even if you could interpolate, it would be a poor Angular Pattern, and could have unexpected outcomes especially in production. Stick to the best practices.

React: Rendering non-existing HTML Element

While reading the React docs, I realized that in JSX, elements starting with a lowercase letter are treated as HTML element. While putting this into practice, I noticed something interesting: When I pass a non-existing, lowercase element, React renders this just fine.
function Foo() {
return (<foo>hello world</foo>);
}
ReactDOM.render(
<Foo />,
document.getElementById('container')
);
This renders like this:
<div id="container">
<foo data-reactroot="">hello world</foo>
</div>
While trying to find an answer on how this is possible, I encountered several projects dealing with Web Components/Custom Elements in React, which confused me a bit.
Does this have something to do with Custom Elements? Will this work in any browser that is supported by React?
No, this has nothing to do with Custom Elements.
It's perfectly fine to create an element which has a tag name that doesn't represent any predefined HTML element. You will get an instance of HTMLUnknownElement:
const myElement = document.createElement('foo');
console.log(myElement.nodeName);
console.log(myElement instanceof HTMLUnknownElement);
Unknown elements don't have special behavior. If you want create a <foo> element which has special behavior, you have to use Custom Elements.
As PeterMader explains, you are creating a custom html element with that syntax. I'll expand on that answer a bit.
First of all it's important to understand that JSX is just a syntactic sugar and that it ultimately transpiles into JavaScript. React elements are created with createElement.
React.createElement(type, props, children);
What's important to note here is that type can be one of the following:
A reference to a React Component (e.g Foo in your example).
A string.
If you are writing React without JSX, then it doesn't matter if you reference a component as foo or as Foo because you have complete control of how you define your variables. In other words, this is plain JavaScript and JSX rules don't apply.
However, if you are using React with JSX, the following rules apply:
type starts with a capital letter = React Component.
type starts with a lowercase letter = HTML element.
In fact, the official documentation says:
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.
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.
So what about <foo />?
In the event that the type of a React Element doesn't resolve into a React Component and is not a standard HTML, React will still treat it as an HTML element.
To my knowledge, React actually doesn't have any whitelist of "valid" HTML tags, but treats anything starting with lowercase the same way. The result in your browser may differ though, as per PeterMader's response.
As such, this (JSX):
<foo>hello world</foo>
will, in modern browsers, yield (HTML):
<foo>hello world</foo>
which is perfectly fine technically, but probably still not a good idea.

React Passing props to background url in template literal

I am learning React and I've run into a snag that I can't seem to fix. In my component that I want the background rendered, I have:
<BgBackground style={{background: 'url({this.props.bg})' }} />
And it takes in it's props from another component with:
<BgImage bg="about" />
I'm writing out my template literal (or interpolation?) incorrectly, I know. I've tried everything such as:
{{backgroundImage: `url( "${this.props.bg}" )` }} />
And I cannot make it work, what am I doing wrong? Thanks for your help!
(back tics are included, they don't render in StackO)
Remove "" inside template literals, whole part inside `` will be treated as string and ${} will be replaced by the value.
Write it like this:
{{backgroundImage: `url(${this.props.bg})`}}
Reference: Template Literals
Update:
Here about is a string (not even a proper image path), import about in this component and pass it like this:
import about from 'path';
<BgImage bg={about" />

Categories

Resources