Variable with the exact name of the component in the scope - reactjs

Just started learning React from zero, regarding components ( when we define them with Uppercase letter), the tutorial is saying
there must be a variable in the scope with that exact name.
I don't understand that and I don't SEE it from the examples of this tutorial.
Here he has:
function MyComponent() {
var data = "world";
return (
<div>
<h1>Hello</h1>
<h2>{data}</h2>
</div>
);
}
Capital Letter. Got it. OK. then we can use it like:
<div>
<div> Greetings </div>
<MyComponent />
</div>
So from that example I can't see and understand what is he talking about. Can someone explain it?

it's talking about what happens behind the scenes.
Your react code you'll be transpiled by babel, and it'll call React.createElelement function. that's why you need to import React.
Remember MyComponent is a function variable after all. React.createElelement calls that function behind the scenes. To be able to call MyComponent (it's when you do <MyComponent />), MyComponent must exists in the first place in the scope where you do <MyComponent />. Meaning, either you have created MyComponent in that scope, or you've imported that variable (as import MyComponent from './<path>/MyComponent') to that scope.

Related

React - is there a way to return JSX which contains braces? [duplicate]

I'm new to React and I'm trying to figure out the purpose/use of <MyComponent></MyComponent> vs <MyComponent />. I can't seem to find information on anything except self-closing tags.
I've created a basic tab scroller as a JSFiddle using the self-closing <MyComponent /> and subsequent props, and I'm wondering if there's a better way to write in React than what I've done.
class TabScroller extends React.Component {
render() {
return (
<div className="tabScroller">
<div className="NavList">
<TabNav handleClick={this.handleNavClick} />
<TabList
tabs={this.state.tabs}
activeTab={this.state.activeTab}
scrollPosition={this.state.scrollPosition}
handleClick={this.handleTabClick}
/>
</div>
<TabContent content={this.state.tabs[this.state.activeTab].content} />
</div>
);
}
}
// ========================================
ReactDOM.render(
<TabScroller />,
document.getElementById('root')
);
In React's JSX, you only need to write <MyComponent></MyComponent> when the component has child components, like this:
<MyComponent>
<Child />
<Child />
<Child />
</MyComponent>
If there is nothing between <MyComponent> and </MyComponent>, then you can write it either <MyComponent/> or <MyComponent></MyComponent> (but <MyComponent/> is generally preferred). Details in Introducing JSX.
Just as a side note, you'd access those children in your component via the special props.children property. More in JSX in Depth: Children in JSX.
Note that this is very much not like HTML or XHTML. It's its own (similar) thing with different rules. For instance, in HTML, <div/> is exactly the same thing as <div>: A start tag, for which you must eventually have an end tag. Not so JSX (or XHTML). The rules for HTML are that void elements (elements that never have markup content, such as br or img) can be written with or without / before > and they never get an ending tag, but non-void elements (like div) must always have an ending tag (</div>), they cannot be self-closing. In JSX (and XHTML), they can be.
The purpose of self-closing tags is simply the fact that it is more compact. This is especially useful when said component doesn't have any children that you typically wrap around a parent.
So usually for leaf components (i.e compoents that do not have any children), you use the self-closing syntax. Like: <Component />. And even if it has props, you can do: <Component foo="bar" />.
However, remember that children is a prop, so you could technically do:
<Component children={<span>foo</span>} />
but I find it less readable and advise against it (read disclaimer below).
To summarize, these are equivalent:
<Component /> = <Component></Component>
<Component foo="bar" /> = <Component foo="bar"></Component>
<Component children={<span>foo</span>}></Component> =
<Component><span>foo</span></Component>
You can use whichever approach you prefer. Though praxis is to use the short-hand version when there are no children.
Disclaimer: While defining childen prop by its object key value will technically work, doing so is strongly discouraged as it disrupts the API as it is meant to be used. Use this version only if confident in what you are doing.

Why component name must be enclosed in tag when we render it

I am just curious why we have to enclose a component name in tags when we render it.
We can do without it also.
For example
function TemporaryName() {
return (
<div>
<h1>Stack Overflow Question</h1>
<h1>Stack Overflow Question</h1>
</div>
)
}
ReactDOM.render(<TemporaryName />, document.getElementById("root"))
This is enclosed and the line
ReactDOM.render(TemporaryName(), document.getElementById("root"))
also gives the same result.
I know there has to be some meaning to it and I want to know why? Please help
Your second example is calling TemporaryName as a function, and then passing the output to render. Basically, it's as though you wrote:
ReactDOM.render((
<div>
<h1>Stack Overflow Question</h1>
<h1>Stack Overflow Question</h1>
</div>
), document.getElementById('root'))
It's fine to pass a <div> into ReactDOM.render, so you didn't see a problem, but you will run into issues with more complicated components. As soon as you try to use any hooks in TemporaryName, you will get an error. You'll be trying to call the hooks before calling ReactDOM.render, which does not work.
Option 1 will work with hooks. With that, you use the JSX tags to create a react element, and pass that element into ReactDOM.render. This doesn't call your function at this time, so there's no misuse of hooks. A little later, react will call your component and the hooks will work since we'll be in the middle of react's render cycle.
Example of something that will fail with the second approach:
function TemporaryName() {
const [name, setName] = useState('Stack Overflow');
return (
<div>
<h1>{name} Question</h1>
<h1>{name} Question</h1>
</div>
)
}
Maybe because when you're declaring your component you're declaring a function: function TemporaryName()

What is this Component and how does it differ from others

I'm self-teaching React and was just wondering if someone could clear something up for me.
I have this component, which seems to be doing everything I need it to:
const Projects = ({ projectData }) => {
const { url } = useRouteMatch();
return (
{projectData.map((project) => (
<div className="project-container" key={project.id}>
<div className="project-image">
</div>
<div>
<h2>{project.name}</h2>
<p>{project.description}</p>
<div>
<Button class="button link_right relative" linkTo={`${url}/${project.id}`} btnText="Explore" />
</div>
</div>
</div>
))}
);
};
export default Projects;
While watching tutorials and reading documentation I'll typically see Function and Class Components but not whatever this is:
const ComponentName = () => {
So, my questions are:
What sort of component is my example known as
What purpose does it
serve when compared to a Function Component or a Class Component,
How would a Function Component or a Class Component need to look in
order to do everything that my example component is currently doing.
Thanks!
Making instance of class is too slow, because of calling constructor and inheritance. Functional components are just functions, there are no such overheads.
In addition, there is how to treat this. In class, entity of this is often unclear and that confused us. Arrow function reduce it, but using class, we must use this. this caused complicated management of state too. And class object has state itself, so it was troublesome.
Function, defined carefully, is easy to keep purity. It has no state itself. It means that state management is not bother us. Data flow is cleared.

Constrain allowed children in React TypeScript

Using TypeScript in a React project is there any way to enforce some constraints on the allowed children of a component? Compile-time is preferred, but run-time could still be helpful.
In my case I have a component, call it <ClickTracker>, and it expects a single child with a callback prop onClick and it adds some extra functionality to the callback (tracking the click in an external library).
This works great as long as the child inside a <ClickTracker> does actually make use of an onClick prop (all HTML elements implement this, for example), but fails silently otherwise.
For example, this works:
<ClickTracker>
<div>Hello</div>
</ClickTracker>
But this doesn't work:
class Hello extends Component<{}, {}> {
render() {
return <div>Hello</div>
}
}
<ClickTracker>
<Hello />
</ClickTracker>
But this does work because it passes onClick to an HTML element:
class Hello extends Component<{onClick: MouseEventHandler}, {}> {
render() {
return <div onClick={this.props.onClick}>Hello</div>
}
}
<ClickTracker>
<Hello />
</ClickTracker>
As you can see I would like to have some safety around what can go inside <ClickTracker> based on the child props. Or if there's another way this could be done.
There is currently, no possible way of enforcing the children type with TypeScript.
There is more information in this issue.
Or if there's another way this could be done
Click events bubble up unless some component stopped propogation (not the default behavior for native components). So you can:
<div onClick={()=>alert('still noted')}>
<Hello />
</div>
And that div is your ClickTracker 🌹

When should I be using React.cloneElement vs this.props.children?

I am still a noob at React and in many examples on the internet, I see this variation in rendering child elements which I find confusing. Normally I see this:
class Users extends React.Component {
render() {
return (
<div>
<h2>Users</h2>
{this.props.children}
</div>
)
}
}
But then I see an example like this:
<ReactCSSTransitionGroup
component="div"
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
{React.cloneElement(this.props.children, {
key: this.props.location.pathname
})}
</ReactCSSTransitionGroup>
Now I understand the api but the docs don't exactly make clear when I should be using it.
So what does one do which the other can't? Could someone explain this to me with better examples?
props.children isn't the actual children; It is the descriptor of the children. So you don't have actually anything to change; you can't change any props, or edit any functionality; you can only read from it. If you need to make any modifications you have to create new elements using React.CloneElement.
https://egghead.io/lessons/react-use-react-cloneelement-to-extend-functionality-of-children-components
An example:
main render function of a component such as App.js:
render() {
return(
<Paragraph>
<Sentence>First</Sentence>
<Sentence>Second</Sentence>
<Sentence>Third</Sentence>
</Paragraph>
)
}
now let's say you need to add an onClick to each child of Paragraph; so in your Paragraph.js you can do:
render() {
return (
<div>
{React.Children.map(this.props.children, child => {
return React.cloneElement(child, {
onClick: this.props.onClick })
})}
</div>
)
}
then simply you can do this:
render() {
return(
<Paragraph onClick={this.onClick}>
<Sentence>First</Sentence>
<Sentence>Second</Sentence>
<Sentence>Third</Sentence>
</Paragraph>
)
}
Note: the React.Children.map function will only see the top level elements, it does not see any of the things that those elements render; meaning that you are providing the direct props to children (here the <Sentence /> elements). If you need the props to be passed down further, let's say you will have a <div></div> inside one of the <Sentence /> elements that wants to use the onClick prop then in that case you can use the Context API to do it. Make the Paragraph the provider and the Sentence elements as consumer.
Edit:
Look at Vennesa's answer instead, which is a better explanation.
Original:
First of all, the React.cloneElement example only works if your child is a single React element.
For almost everything {this.props.children} is the one you want.
Cloning is useful in some more advanced scenarios, where a parent sends in an element and the child component needs to change some props on that element or add things like ref for accessing the actual DOM element.
In the example above, the parent which gives the child does not know about the key requirement for the component, therefore it creates a copy of the element it is given and adds a key based on some unique identifier in the object. For more info on what key does: https://facebook.github.io/react/docs/multiple-components.html
In fact, React.cloneElement is not strictly associated with this.props.children.
It's useful whenever you need to clone react elements(PropTypes.element) to add/override props, without wanting the parent to have knowledge about those component internals(e.g, attaching event handlers or assigning key/ref attributes).
Also react elements are immutable.
React.cloneElement( element, [props], [...children] ) is almost equivalent to:
<element.type {...element.props} {...props}>{children}</element.type>
However, the children prop in React is especially used for containment (aka composition), pairing with React.Children API and React.cloneElement, component that uses props.children can handle more logic(e.g., state transitions, events, DOM measurements etc) internally while yielding the rendering part to wherever it's used, React Router <switch/> or compound component <select/> are some great examples.
One last thing that worth mentioning is that react elements are not restricted to props.children.
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />
);
}
They can be whatever props that makes sense, the key was to define a good contract for the component, so that the consumers of it can be decoupled from the underlying implementation details, regardless whether it's using React.Children, React.cloneElement, or even React.createContext.

Resources