arrow-left

All pages
gitbookPowered by GitBook
1 of 2

Loading...

Loading...

React components

Learn the basics of creating DOM elements using JSX and React components

React makes dealing with the DOM in JavaScript more like writing HTML. It helps package up elements into "components" so you can divide your UI up into reusable pieces.

hashtag
React elements

Interacting with the DOM can be a frustrating experience. It requires lots of awkward lines of code where you tell the browser exactly how to create an element with the right properties.

Even if we create our own function to handle some of the repetitive parts it's a little hard to read:

This is frustrating because there is a simpler, more declarative way to create elements: HTML.

Unfortunately we can't use HTML inside JavaScript files. HTML can't create elements dynamically as a user interacts with our app. This is where React comes in:

This variable is a React element. It's created using a special syntax called that lets us write HTML-like elements within our JavaScript.

The example above will be transformed into this normal JS:

This function call returns an object that describes your element:

React builds up one big tree structure of all these element objects that represents your entire app. It then uses this tree to create the actual DOM elements for you. (This is called the virtual DOM, but you don't need to worry about that right now)

It can be helpful to remember that the HTML-like syntax is really normal function calls that return objects.

hashtag
Templating dynamic values

JSX supports inserting dynamic values into your elements. It uses a similar syntax to JS template literals: anything inside curly brackets will be evaluated as a JS expression, and the result will be rendered. For example:

You can do all kinds of JS stuff inside the curly brackets, like referencing other variables, or conditional expressions.

hashtag
Note on expressions

You can put any valid JS expression inside the curly brackets. An expression is code that resolves to a value. I.e. you can assign it to a variable. These are all valid expressions:

This is not a valid expression:

if blocks are statements, not expressions. The main impact of this is that you have to use ternaries instead of if statements inside JSX.


hashtag
React components

React elements aren't very useful on their own. They're just static objects. To build an interface we need something reusable and dynamic, like functions.

A React component is a function that returns a React element.

hashtag
Valid elements

A React element can be a JSX element, or a string, number, boolean or array of JSX elements. Returning null, undefined, false or "" (empty string) will cause your component to render nothing.

hashtag
Composing components

Components are useful because JSX allows us to compose them together just like HTML elements. We can use our Title component as JSX within another component. It's like making your own custom HTML tags.

When we use a component in JSX (<Title />) React will find the corresponding Title function, call it, and use whatever element it returns.

hashtag
Customising components

A component where everything is hard-coded isn't very useful. It will always return the exact same thing, so there's almost no point being a function. Functions are most useful when they take arguments. Passing different arguments lets us change what the function returns each time we call it.

JSX supports passing arguments to your components. It does this using the same syntax as HTML:

React component functions only ever receive one argument: an object containing all of the arguments passed to it. React will gather up any key="value" arguments from the JSX and create this object.

This object is commonly named "props" (short for properties). Using an object like this means you don't have to worry the order of arguments. So in this case our Title function will receive a single argument: an object with a "name" property.

You can use these props within your components to customise them. For example we can interpolate them into our JSX to change the rendered HTML:

Now we can re-use our Title component to render different DOM elements:

hashtag
Non-string props

Since JSX is JavaScript it supports passing any valid JS expression to your components, not just strings. To pass JS values as props you use curly brackets, just like interpolating expressions inside tags.

hashtag
Children

It would be nice if we could nest our components just like HTML. Right now this won't work, since we hard-coded the text inside our <h1>:

JSX supports a special prop to achieve this: children. Whatever value you put between JSX tags will be passed to the component function as a prop named children. You can then access and use it exactly like any other prop.

Now this JSX will work as we expect:

This is quite powerful, as you can now nest your components to build up more complex DOM elements.

hashtag
Rendering to the page

You may be wondering how we get these React components to actually show up on the page.

React consists of two libraries—the main React library and a specific ReactDOM library for rendering to the DOM (since React can also to render Virtual Reality or Native mobile apps).

We use the ReactDOM.render() function to render a component to the DOM. It takes an element as the first argument and a DOM node as the second.

It's common practice to have a single top-level App component that contains all the rest of the UI.

hashtag
Challenge

Time to create some components! Open up challenge.html in your editor. You should see the components we created above. Open this file in your browser too to see the components rendered to the page.

Create a new component called Card. It should take 3 props: title, image and children, that render into h2, img and p elements respectively.

Replace the p in the App component with a Card. Pass whatever you like as the 3 props (although here's an image URL you can use: https://source.unsplash.com/400x300/?burger).

const title = document.createElement("h1");
title.className = "title";
title.textContent = "Hello world!";
JSXarrow-up-right
const title = createEl("h1", { className: "title" }, "Hello world!");
<h1 class="title">Hello world!</h1>
const title = <h1 className="title">Hello world!</h1>;
const title = React.createElement("h1", { className: "title" }, "Hello world!");
// over-simplified for examples sake
const title = {
  type: "h1",
  props: {
    className: "title",
    children: "Hello world!",
  },
};
const title = <h1>Hello {5 * 5}</h1>;
// <h1>Hello 25</h1>
const name = "oli";
const title = <h1>Hello {name}</h1>;
// <h1>Hello oli</h1>
const number = Math.random();
const result = <div>{number > 0.5 ? "You won!" : "You lost"}</div>;
// 50% of the time: <div>You won!</div>
// the other 50%: <div>You lost</div>
const number = 5 + 4 * 9;
const isEven = number % 2 === 0;
const message = isEven ? "It is even" : "It is odd";
const message = if (isEven) { "It is even" } else { "It is odd" };
// this is not valid JS and will cause an error
function Title() {
  return <h1 className="title">Hello world!</h1>;
}
function Title() {
  return <h1 className="title">Hello world!</h1>;
}

function Page() {
  return (
    <div className="page">
      <Title />
    </div>
  );
}
<Title name="oli" />
function Title(props) {
  console.log(props); // { name: "oli" } (assuming <Title name="oli" /> was used)
  return <div className="title">Hello world</div>;
}
function Title(props) {
  return <div className="title">Hello {props.name}</div>;
}
function Page() {
  return (
    <div className="page">
      <Title name="oli" />
      <Title name="sam" />
    </div>
  );
}
// <div class="page"><h1 class="title">Hello oli</h1><h1 class="title">Hello sam</h1></div>
function Page() {
  const customName = "oliver" + " phillips";
  return (
    <div className="page">
      <Title name={customName} />
      <Title name={5 * 5} />
    </div>
  );
}
// <div class="page"><h1 class="title">Hello oliver phillips</h1><h1 class="title">Hello 25</h1></div>
<Title>Hello oli</Title>
function Title(props) {
  return <div className="title">{props.children}</div>;
}
<Title>Hello oli</Title>
// <h1 class="title">Hello oli</h1>
// pretend we have defined Image and BigText components above
<Title>
  <Image src="hand-wave.svg" />
  <BigText>Hello oli</BigText>
</Title>
function App() {
  return (
    <Page>
      <Title>Hello world!</Title>
      <p>Welcome to my page</p>
    </Page>
  );
}

const rootNode = document.querySelector("#root");
ReactDOM.render(<App />, rootNode);

react-components

task example