A Basic Component
// App.js
import React from 'react';
function App() {
return (
<div>
<h1>Welcome to React</h1>
<p>This is some basic content.</p>
</div>
);
}
export default App;
We use ES2015 (ES6) style import
/export
s to include react
.
Our App
function returns what looks like HTML
but is actually something called JSX
.
JSX
JSX lets us blur the lines between JavaScript and HTML by allowing us to write code like this:
const element = <h1>Hello, world!</h1>;
This is a variable that's holding a reference to an h1 element.
We can define that JSX inline...
function Header() {
return (
<header>
<div className="logo">
<img src="static/img/logo.png" alt="Logo" />
</div>
</header>
);
}
export default Header
Rendering a JSX Variable
We can also render a variable that's holding some JSX like this:
import React from "react";
function App() {
const logo = <img src="static/img/logo.png" alt="Logo" />;
return (
<header>
<div className="logo">
{logo}
</div>
</header>
);
}
export default App;
The curly braces around the {logo}
reference let us write JavaScript inside our JSX.
Rendering a Sub-Component
We can also import a Component
from another file and render it like so:
import Logo from './Logo';
function Header() {
return (
<header>
<Logo />
</header>
);
}
export default Header
That's really powerful, because it lets us break a complex UI down into smaller pieces.
React gives us the ability to use encapsulation and abstraction in tandem with the expressiveness of HTML.
class
and className
in JSX
Did you notice the className
attribute in the earlier example?
function Header {
return (
<header>
<div className="logo">
<img src="static/img/logo.png" alt="Logo" />
</div>
</header>
);
}
export default Header
Since class
is a keyword in JavaScript, we can't use the traditional css class
attribute in JSX
.
Instead, we use className
which behaves as you would expect.
this.props
Props allow data to flow from parent components into their children.
Children should NEVER make changes to props.
What if we had both a black and white and color version of our logo Logo
component.
function Logo() {
const imageUrl = this.props.isColor ?
'/images/logo-color.png' :
'/images/logo-bw.png';
return (
<div className="logo">
<img src={imageUrl} alt="Logo" />
</div>
);
}
export default Logo
Now, when someone wants to use the logo they can just set the isColor
property to true
or false
.
Of course, we could pass true instead.
function Header() {
return (
<header>
<Logo isColor={true} />
</header>
);
}
export default Header
If we include the isColor
attribute with no value, React will assign it as being true
.
This is equivalent to the above example:
function Header() {
return (
<header>
<Logo isColor />
</header>
);
}
export default Header
Importing CSS
We can write small, focused css
files that live beside our components.
By importing these css files, they'll be bundled up and included in our application as a single css file.
JSX and Separation of Concerns
JSX usually turns heads when people first see it. It's been steadily beat into everyone's head that HTML, CSS, and JS are separate things that each belong in their own file. In JSX it doesn't exactly work that way. But you can still pay attention to separation of concerns.
Imagine if we were adding a CustomerTestimonial
widget to an application.
index.html
: Modify to add some HTML that structures the Customer Testimonial.index.css
: Modify the CSS to add some styles for the Customer Testimonial.index.js
: Modify the JS to add behavior to the Customer Testimonial (maybe)
Is that really a separation of concerns, though?
If we wanted to add CustomerTestimonial
to another page on our app, how would we go about it?
Perhaps we don't have as great a separation of concerns as we thought.
Making Things Modular
In React, we might create a Component
that represents a customer testimonial widget like so:
import React from 'react';
import './CustomerTestimonial.css';
function CustomerTestimonial() {
const defaultImageUrl = '/img/default-customer-image.png';
const { quote, name, company, imageUrl } = this.props;
return (
<div className="testimonial">
<img src={imageUrl || defaultImageUrl}
alt="Customer"
/>
<div className="quote">
<p>{quote}</p>
<span className="name">{name}</span>
<span className="company">{company}</span>
</div>
</div>
);
}
export default CustomerTestimonial;
Using the CustomerTestimonial
We can use this component anywhere we want in our application by simply importing it and using it.
import React from "react";
import CustomerTestimonial from './CustomerTestimonial';
function App() {
return (
<CustomerTestimonial
imageUrl="/img/foo.jpg"
quote="Totally not bad."
name="Chad McChad"
company="Chad's Light Bulbs, Inc" />
);
}
export default App;
First, we import the component.
Next we reference the component as if it were an HTML component inside JSX.
We can even pass data into our component via it's props
Encapsulation
With a single line of code,
import CustomerTestimonial from './CustomerTestimonial';
We can import that component anywhere we need it, and we'll get everything that the component needs to do it's job.
That's pretty awesome.
Conclusion
Components are at the heart of absolutely every React application you will ever write. It's also slowly creeping in as the default method of organization in many frameworks and even in the DOM API with Web Components. So getting comfortable with this ecosystem is going to pay off in the long run for building web applications.