CHAPTER 3React Components
A component is just a function that will render some data in JSX.
We saw a function rendering a User
in the last chapter:
function renderUser(name: string, age: number) {
return (
<div>
<span>{name}</span>
<span>{age}</span>
</div>
);
}
In past versions of React (still today) components could also be classes, but this style is not the dominant anymore, even if a lot of code is still written in that style
Props
But there is very important convention: function components can receive only one parameter, which is an object.
type UserProps = {
name: string;
age: numger;
};
const User = (props: UserProps) => (
<div className="user">
<span className="name">{props.name}</span>
<span className="age">{props.age}</span>
</div>
);
Instead of passing data as multiple parameters, all data is passed as a single
object, called props
. In a sense, these object represents the "properties" of
the component.
When using a props
object you can destructure the fields of the object
before-hand, such as not to carry the prefix props.
in the code inside the
component.
type UserProps = {
name: string;
age: numger;
};
const User = ({ name, age }: UserProps) => (
<div className="user">
<span className="name">{name}</span>
<span className="age">{age}</span>
</div>
);
Functional Style
The props
of a component are its input data, and therefore, from a programming
perspective, they are input paramenters, which are read-only. A React component
is, therefore, a pure function, one that will only depend on the values of the
props
, and keeps nothing or uses nothing else. This is the only way in which
React can rest assured that its job will be effective. If components weren't
pure the job of React would be much more difficult.
Calling Components
To use a component, you can call the function directly, of course:
<p>{User({ name: "johndoe", age: 27 })}</p>
but here is where JSX can make things a lot better and easier to read.
Instead of calling the function directly, in React you can just call it by
pretending that an element exists with that name, and the attributes are the
fields in the props
object:
<p>
<User name="johndoe" age={27} />
</p>
The <User ... />
element will transform into a call to the User
function,
and that is what gives us Element Abstraction, i.e., the ability to define ever
more complex elements to solve problems at the highest possible level.
An important rule about components:
- They have to start in UpperCase. To distinguish HTML elements from React
components, JSX just uses the name of the function: if it starts in upper-case
it is a component (
User
,Card
,MyButton
,Movie
), otherwise it is a normal HTML element (div
,span
,p
,em
,article
,header
, ...)
Children
If the component has an opening tag and a closing tag, such as in:
<BounceEffect>{/* ... */}</BounceEffect>
then the elements inside of it are its children
. The props, therefore, will
contain a children
field with an array of the children, which we can
const BounceEffect = ({ children }) => (
<div className="outer">
<div className="inner">{children}</div>
</div>
);
Components as files
Typically, unless we create tiny components, the most common way to develop
React components is to put each component in a separated file. So our User
component would be in file User.tsx
(notice that the filename is in
uppercase):
// User.tsx
type UserProps = {
name: string;
age: numger;
};
export default function User (props: UserProps) (
<div className="user">
<span className="name">{props.name}</span>
<span className="age">{props.age}</span>
</div>
);
To be able to export default
the component and name it at the same
time(although it would not be strictly necessary) it is useful to adopt the
function
notation since arrow functions would not allow naming or would need
to do the export default
separately.