Components and Props
➞Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.➞Conceptually, components are like JavaScript functions.
➞They accept arbitrary inputs (called "props") and return React elements describing what should appear on the screen.
⟹Functional and Class Components
➞The simplest way to define a component is to write a JavaScript function:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
➞We call such components "functional" because they are literally JavaScript functions.
➞You can also use an ES6 class to define a component:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
⟹Rendering a Component
➞Previously, we only encountered React elements that represent DOM tags:const element = <div />;
const element = <Welcome name="Sara" />;
➞We call this object "props".
➞For example, this code renders "Hello, Sara" on the page:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
- We call
ReactDOM.render()
with the<Welcome name="Sara" />
element. - React calls the
Welcome
component with{name: 'Sara'}
as the props. - Our
Welcome
component returns a<h1>Hello, Sara</h1>
element as the result. - React DOM efficiently updates the DOM to match
<h1>Hello, Sara</h1>
.
➞Caveat:
➞Always start component names with a capital letter.
➞For example,<div />
represents a DOM tag, but<Welcome />
represents a component and requiresWelcome
to be in scope.
⟹Composing Components
➞Components can refer to other components in their output.➞This lets us use the same component abstraction for any level of detail.
➞A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components.
➞For example, we can create an
App
component that renders Welcome
many times:function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
➞Typically, new React apps have a single
App
component at
the very top. ➞However, if you integrate React into an existing app, you might start bottom-up with a small component like
Button
and gradually work your way to the top of the view hierarchy.➞Caveat:
➞Components must return a single root element.➞This is why we added a
<div>
to contain all the <Welcome />
elements.⟹Extracting Components
➞Don't be afraid to split components into smaller components.➞For example, consider this
Comment
component:function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
➞It accepts
author
(an object), text
(a string), and date
(a date) as props, and describes a comment on a social media website.➞This component can be tricky to change because of all the nesting, and it is also hard to reuse individual parts of it. Let's extract a few components from it.
➞First, we will extract
Avatar
:function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar
doesn't need to know that it is being rendered inside a Comment
. ➞This is why we have given its prop a more generic name:
user
rather than author
.➞We recommend naming props from the component's own point of view rather than the context in which it is being used.
➞We can now simplify
Comment
a tiny bit:function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
UserInfo
component that renders an Avatar
next to user's name:function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
Comment
even further:function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
➞Extracting components might seem like grunt work at first, but having a palette of reusable components pays off in larger apps.
➞A good rule of thumb is that if a part of your UI is used several times (
Button
, Panel
, Avatar
), or is complex enough on its own (App
, FeedStory
, Comment
), it is a good candidate to be a reusable component.⟹Props are Read-Only
➞Whether you declare a component as a function or a class, it must never modify its own props.➞Consider this
sum
function:function sum(a, b) {
return a + b;
}
➞In contrast, this function is impure because it changes its own input:
function withdraw(account, amount) {
account.total -= amount;
}
➞React is pretty flexible but it has a single strict rule:➞All React components must act like pure functions with respect to their props.
➞Of course, application UIs are dynamic and change over time.
➞State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.
No comments:
Post a Comment