What is the smallest building block of ReactJS - Elements or Components? - reactjs

In React JS documentation,
it is mentioned Elements are the smallest building blocks of ReactJS.
But, Components are also built, in order to create Elements.
For example,
const element = <Welcome name="Sara" title="Mara"/>;
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
So, Component (here Welcome function component) was smallest building block that helped create an Element.
So, Does it mean Components are the smallest building blocks? It is confusing. Please clarify.

A react component is made up of simple html elements. But a react component's smallest element is the react component itself.
A react component is actually an object with fields {type:..., state:..., props:...., children:....,} Where children will be componsed of other subtree objects(react elements). This object is used for calculating the difference in dom when a component is rerendered(on change of state or props) and pushing the objects with change and ignoring those which doesnt change.

React is all about components. When you have complex DOM ( DOM is made up of elements ) it's React's way to break that complex DOM into granular smaller components.
The more granular it is, you are doing it the more React way (It's a React best practice).
coming to "Components are the smallest build blocks ?", well we can't say it that way, we can say "React is all about components"
It depends on us that how well we create granular components, which makes it easily reusable and maintainable.
Creating granular components always doesn't mean creating components with just one element.
Granular Component ?
import React from 'react';
const welcome = (props) => (
<div>
<p>props.welcomeMessage</p>
<h3>Disclaimer</h3>
<p>props.disclaimerMessage</p>
</div>
);
export default welcome;
I can call this a granular component but we can also debate on the Disclaimer part of this code, Disclaimer also can be used elsewhere so it's always a good practice to identify such pieces and move them into there own components so that we get the complete benefits of React
We cannot call a component the smallest building block but yes we can break the HTML into proper, well-structured Component Tree to get the smallest ones.

Elements and Components are different things in React, and the documentation you read explains the first of those, the element.
Elements:
Elements are plain JavaScript objects that describe how your UI should be rendered.
If you are using JSX, describing elements looks quite similar to writing HTML.
// The `<div />` is JSX for creating a React *Element*
const element = <div>Foo</div>;
Components:
Components are separate from elements. As mentioned in the Components and Props doc, components are "like JavaScript functions" and "return React elements describing what should appear on the screen."
React Components return React Elements describing what should appear on the screen
// This is a React *Component*: a Function that returns a React *Element*.
function MyComponent() {
return <div>Foo</div>;
}
// You can also implement a React *Component* by extending `React.Component`
// and implementing a `render` method.
class YourComponent extends React.Component {
render() {
return <div>Foo</div>;
}
}

Related

Multiple JSX elements with react

If we want to write multiple JSX elements we must wrap it with parent element or React Fragment element to be rendered successfully , Is there any way to write multipe jsx elements without need to wrap it with any parent or fragment element (like maybe make the fragment by default behind the scene without need to write it ) ,
function CustomBtn() {
return (
<h1>CustomBtn</h1>
<h1>CustomBtn</h1>
)
}
i know this will give Parsing error: Adjacent JSX elements must be wrapped in an enclosing tag
i know that it's useless , because we can just use react fragment , but it's like a training task to dig deeper into react configuration
i think in babel , webpack or react dom packages but i can't solve it , any ideas ?
Thanks
This is a good idea. But this is not customizable for the following reason.
React team made the interface of a component to be a single ReactNode. But for some functions, they also allow for an array of nodes, ReactNode[]. To be honest, internally they do support array, otherwise you won't be able to do {arr.map(v => <div />).
Therefore this is not something that you like or not, it's the interface definition of a React component. Imagine you design the component, you can choose to accept an array or a single. If you were the author, you could make that happen ;)
NOTE:
deep down there's another reason, each component accepts a ref. The ref is the DOM element reference, so a single mapping from one ref to a single React node is a more straightforward implementation.
You can return array:
function CustomBtn() {
return [
<h1>CustomBtn</h1>,
<h1>CustomBtn</h1>
]
}

How to lazy-load a React "widget"?

My terminology is probably wrong here, but I don't know what to call it other than a "widget" when you don't have a whole React app, but are attaching little React pieces to different roots on an otherwise static HTML page. But, that's what I'm doing:
const StripeForm = React.lazy(() => import('./Stripeform'));
// ...
const formPlaceholder = document.getElementById('cwr-stripe-form');
const formRoot = createRoot(formPlaceholder);
formRoot.render(
<React.StrictMode>
<StripeForm />
</React.StrictMode>
);
The problem I'm trying to solve is, I want to lazy-load my StripeForm, so that it doesn't load until needed (and therefor maybe never at all).
I have the React.lazy import and my webpack bundle working fine. The issue is "until needed".
As I understand it, lazy-loaded components load when they begin rendering, which I suppose is usually when they move into the viewport. And I equally suppose that "usually" is overridden by the fact that I'm calling .render, which I guess causes it to render immediately.
Those guesses might be wrong, but the fact is, when I load my web page, the supposedly lazy-loaded component is loaded, even if it's not in the viewport.
How to I get these sort of "widgets" (there are several others on the page) to load lazily (i.e., to attach to my root placeholder element, but not actually load and render until necessary)?
You're already using lazy, so React will only import the component if it's not being rendered. The problem is that you're still rendering the component by default, so the component is still being loaded once it's available.
React is declarative, so the way to solve this is to conditionally render the component only when you want it to be rendered. You can implement this by using a visibility library such as react-is-visible, for example:
import React, { useRef } from 'react'
import { useIsVisible } from 'react-is-visible'
function LazyStripeForm() {
const ref = useRef()
const isVisible = useIsVisible(ref, { once: true })
return <div ref={ref}>{isVisible && <StripeForm />}</div>
}
Now you can render LazyStripeForm instead of StripeForm and it should do what you want.
Also, if StripeForm has a lot of dependencies, you should ensure your build tool is code splitting the file so that it's not increasing the size of your main bundle unnecessarily.

How does React provide independent contexts for subtrees?

If, as a thought experiment, I were to write my own createElement implementation for JSX, what might support for implicit context look like?
In particular, I can't figure out how with the limited means of JSX's createElement signature, contexts can be independent for different subtrees. (It appears React's Context handling has become more elaborate in recent versions; I'm mostly interested in the seemingly more straightforward mechanisms of earlier versions.)
This might be used to automatically determine heading levels, for example:
<Section title="Hello World">
<Card title="Details" />
</Section>
<Card title="Example" />
Here Card would automatically generate <h3> and <h2>, respectively, by relying on something like context.headingLevel.
A very nice question, that shows how different is the concept of creating React Elements to actually executing the render functions (either the .render method of class components or simply the main body of a functional component).
In JSX itself (which is just React.createElement(…)) there‘s no concept of “context” at all. It comes into existance only when the components are rendered. It is indeed a duty of the React Renderer (such as React DOM or React Native) to actually implement Context APIs.
If you remove the ability to store states and to update the UI you are left with a minimal React implementation that only “renders once”, but perfectly fine to understand the problem at hand.
Everytime the React Renderer needs to render a React Elements tree (such as one built with JSX) it passes every single element and transforms it into a DOM structure, but when it encounters a component node (not a “native” element) it needs to render it to obtain its React Element sub tree, and swap the original node with it.
It’s in this specific moment that React can keep track of which Context values to pass to which components, since it is traversing the tree.
So, to answer directly your question, you can’t implement context in the “element creation phase”, inside your JSX implementation, you need to do it in a subsequent phase when you can traverse the tree.
If you were trying to build an “immediate JSX” you probably have something like this:
function createElement(type, props, ...children) {
props = { children, ...props };
if (typeof type === 'function') {
return type(props);
} else {
return { type, props };
}
}
In thise case you will not be able to implement an API similar to context, because the execution order is inner-then-outer:
const div = createElement('div', {}, createElement(Card, {}));
// identical to
const card = createElement(Card, {}); // inner, and then…
const div = createElement('div', {}, card); // outer

React.forwardRef is already possible without it, so what's the use of it?

I'm confused on the point of React.forwardRef. As explained in its documentation, I understand that its main use is for a Parent Component to gain access to DOM elements of the Child Component. But I can already do that without even having to use it.
Here is a code example that you can plug into CodeSandbox and see that it works:
import React, {useRef, useEffect} from "react";
import "./styles.css";
const ChildComponent = (props) => {
useEffect( ()=> {
props.callbackFunction()
})
return(
<div ref={props.fRef}>
{"hello"}
</div>
)
}
export default function App() {
const callbackFunction = () => {
console.log("The parent is now holding the forwarded ref to the child div: ")
console.log(forwardedRef)
}
const forwardedRef = useRef(null)
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
</div>
);
}
Or here's the embed of this example. Honestly, I'm kind of new to this and I don't know exactly how embeds work and whether someone fiddling with the embed changes my original Sandbox or not, so I was hesitant to put it. But here it is.
Example Forwarding Ref
In the example, the parent App() component successfully passes a ref to the child which the child attaches to its rendered div. After it renders, it calls a callback function to the parent. The parent then does a console log where it proves that its forwarded ref now has a hold of the child's div. And this is all done without React.forwardRef.
So what then is the use for React.forwardRef?
You're absolutely right that you can do what you've described. The downside is that you're forced to expose an API (ie: the fRef prop) for it to work. Not a huge deal if you're a solo developer building an app, but it can be more problematic eg. if you're maintaining an open-source library with a public API.
In that case, consumers of the library won't have access to the internals of a component, meaning you'd have to expose it for them somehow. You could simply do what you're suggesting in your example and add a named prop. In fact, that's what libraries did before React 16.3. Not a huge deal, but you'd have to document it so people know how to use it. Ideally, you'd also want some kind of standard that everyone used so it wasn't confusing (many libraries used the innerRef naming convention), but there'd have to be some consensus around that. So all doable, but perhaps not the ideal solution.
Using forwardRef, passing a ref to a component just works as expected. The ref prop is already standardized in React, so you don't need to go look at docs to figure out how to pass the ref down or how it works. However, the approach you describe is totally fine and if it meets your needs, by all means go with that.
As mentioned in the docs , it's useful for highly reusable components, meaning components that tend to be used like regular HTML DOM elements.
This is useful for component libraries where you have lots of "leaf" components. You've probably used one like Material UI.
Example:
Let's say you're maintaining a component library.
You create a <Button/> and <Input/> component that maybe just adds some default styling.
Notice how these components literally are just like regular HTML DOM elements with extra steps.
If these components were made to be used like regular HTML DOM elements, then I expect all the props to be the same, including ref, no?
Wouldn't it be tedious if to get the button ref from your <Button/> component I'd have to get it through something like fRef or buttonRef ?
Same with your <Input/>, do I have to go to the documentation just to find out what ref to use and it's something like inputRef ? Now I have to memorize?
Getting the ref should be as simple as <Button ref={}/>
Problem
As you might know, ref will not get passed through props because, like key, it is handled differently by React.
Solution
React.forwardRef() solves this so I can use <Button ref={}/> or <Input ref={}/>.

Passing components as props? Compositional vs Higher Order Components

I'm creating some layout-level components for my React app. As I understand it there are two main design patterns I can utilize - compositional, and higher-order components.
Am I correct in thinking that I have to make use of props.children when I want to create a wrapper component in the compositional style?
And am I correct in thinking that if I want to, say, pass in two different components (as in the Higher-Order Components example below), I have to make use of the higher-order component style?
Compositional:
const CenteredColumn = props => (
<div className="columns">
<div className="column is-8 is-offset-2">{props.children}</div>
</div>
);
Higher Order Component:
const withTwoColumns = ({ first, second }) => (
<div className="columns">
<div className="column">{first}</div>
<div className="column">{second}</div>
</div>
);
Yes you are right. The compositional style allows you to pass children to components ahead of time before they are aware that they have them. So we could do this:
Please see: https://facebook.github.io/react/docs/composition-vs-inheritance.html
So to the h1 and p tags, the div with a className of 'fancyborder' will cover/wrap/surround them.
Regarding HOCS, you are also correct. They are components they receive other component(s) as inputs and render component(s) as the output.
Pardon me not providing code. I used a touch device. Hope this helped.
Both work. From the way you're writing it, it's a coding style/hierarchical choice. There are anti-patterns for React, but this is not one of them.
The way you should you set your layout is by dividing your workflow or proyect structure in presentatational ( Stateless) components and Container components.. The presentationals components will only receive props from their main components while the container components will contain the logic of the applications.

Resources