How To Create A Component In React
The author selected Creative Commons to receive a donation as part of the Write for DOnations program.
Introduction
In this tutorial, you'll learn to create custom components in React. Components are independent pieces of functionality that you can reuse in your application, and are the building blocks of all React applications. Often, they can be simple JavaScript functions and classes, but you use them as if they were customized HTML elements. Buttons, menus, and any other front-end page content can all be created as components. Components can also contain state information and display markdown.
After learning how to create components in React, you'll be able to split complex applications into small pieces that are easier to build and maintain.
In this tutorial, you'll create a list of emojis that will display their names on click. The emojis will be built using a custom component and will be called from inside another custom component. By the end of this tutorial, you'll have made custom components using both JavaScript classes and JavaScript functions, and you'll understand how to separate existing code into reusable pieces and how to store the components in a readable file structure.
Prerequisites
-
You will need a development environment running Node.js; this tutorial was tested on Node.js version 10.20.1 and npm version 6.14.4. To install this on macOS or Ubuntu 18.04, follow the steps in How to Install Node.js and Create a Local Development Environment on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.
-
You will need to be able to create apps with Create React App. You can find instructions for installing an application with Create React App at How To Set Up a React Project with Create React App.
-
You will be using JSX syntax, which you can learn about in our How To Create Elements with JSX tutorial.
-
You will also need a basic knowledge of JavaScript, which you can find in How To Code in JavaScript, along with a basic knowledge of HTML and CSS. A good resource for HTML and CSS is the Mozilla Developer Network.
Step 1 — Setting Up the React Project
In this step, you'll create a base for your project using Create React App. You will also modify the default project to create your base project by mapping over a list of emojis and adding a small amount of styling.
First, create a new project. Open a terminal, then run the following command:
- npx create-react-app tutorial-03-component
Once this is finished, change into the project directory:
- cd tutorial-03-component
Open the App.js
code in a text editor:
- nano src/App.js
Next, take out the template code created by Create React App, then replace the contents with new React code that displays a list of emojis:
tutorial-03-component/src/App.js
import React from 'react'; import './App.css'; const displayEmojiName = event => alert(event.target.id); const emojis = [ { emoji: '😀', name: "test grinning face" }, { emoji: '🎉', name: "party popper" }, { emoji: '💃', name: "woman dancing" } ]; function App() { const greeting = "greeting"; const displayAction = false; return( <div className="container"> <h1 id={greeting}>Hello, World</h1> {displayAction && <p>I am writing JSX</p>} <ul> { emojis.map(emoji => ( <li key={emoji.name}> <button onClick={displayEmojiName} > <span role="img" aria-label={emoji.name} id={emoji.name}>{emoji.emoji}</span> </button> </li> )) } </ul> </div> ) } export default App;
This code uses JSX syntax to map()
over the emojis
array and list them as <li>
list items. It also attaches onClick
events to display emoji data in the browser. To explore the code in more detail, check out How to Create React Elements with JSX, which contains a detailed explanation of the JSX.
Save and close the file. You can now delete the logo.svg
file, since it was part of the template and you are not referencing it anymore:
- rm src/logo.svg
Now, update the styling. Open src/App.css
:
- nano src/App.css
Replace the contents with the following CSS to center the elements and adjust the font:
tutorial-03-component/src/App.css
.container { display: flex; flex-direction: column; align-items: center; } button { font-size: 2em; border: 0; padding: 0; background: none; cursor: pointer; } ul { display: flex; padding: 0; } li { margin: 0 20px; list-style: none; padding: 0; }
This uses flex
to center the main <h1>
and list elements. It also removes default button styles and <li>
styles so the emojis line up in a row. More details can be found at How to Create React Elements with JSX.
Save and exit the file.
Open another terminal window in the root of your project. Start the project with the following command:
- npm start
After the command runs, you'll see the project running in your web browser at http://localhost:3000
.
Leave this running the entire time you work on your project. Every time you save the project, the browser will auto-refresh and show the most up-to-date code.
You will see your project page with Hello, World and the three emojis that you listed in your App.js
file:
Now that you've set up your code, you can now start putting together components in React.
Step 2 — Creating an Independent Component with React Classes
Now that you have your project running, you can start making your custom component. In this step, you'll create an independent React component by extending the base React Component
class. You'll create a new class, add methods, and use the render function to show data.
React components are self-contained elements that you can reuse throughout a page. By making small, focused pieces of code, you can move and reuse pieces as your application grows. The key here is that they are self-contained and focused, allowing you to separate out code into logical pieces. In fact, you have already been working with logically separated components: The App.js
file is a functional component, one that you will see more of in Step 3.
There are two types of custom component: class-based and functional. The first component you are going to make is a class-based component. You will make a new component called Instructions
that explains the instructions for the emoji viewer.
Note: Class-based components used to be the most popular way of creating React components. But with the introduction of React Hooks, many developers and libraries are shifting to using functional components. Though functional components are now the norm, you will often find class components in legacy code. You don't need to use them, but you do need to know how to recognize them. They also give a clear introduction to many future concepts, such as state management. In this tutorial, you'll learn to make both class and functional components.
To start, create a new file. By convention, component files are capitalized:
- touch src/Instructions.js
Then open the file in your text editor:
- nano src/Instructions.js
First, import React
and the Component
class and export Instructions
with the following lines:
tutorial-03-component/src/Instructions.js
import React, { Component } from 'react'; export default class Instructions extends Component {}
Importing React
will convert the JSX. Component
is a base class that you'll extend to create your component. To extend that, you created a class that has the name of your component (Instructions
) and extended the base Component
with the export
line. You're also exporting this class as the default with export default
keywords at the start of the class declaration.
The class name should be capitalized and should match the name of the file. This is important when using debugging tools, which will display the name of the component. If the name matches the file structure, it will be easier to locate the relevant component.
The base Component
class has several methods you can use in your custom class. The most important method, and the only one you'll use in this tutorial, is the render()
method. The render()
method returns the JSX code that you want to display in the browser.
To start, add a little explanation of the app in a <p>
tag:
tutorial-03-component/src/Instructions.js
import React, { Component } from 'react'; export class Instructions extends Component { render() { return( <p>Click on an emoji to view the emoji short name.</p> ) } }
Save and close the file. At this point, there's still no change to your browser. That's because you haven't used the new component yet. To use the component, you'll have to add it into another component that connects to the root component. In this project, <App>
is the root component in index.js
. To make it appear in your application, you'll need to add to the <App>
component.
Open src/App.js
in a text editor:
- nano src/App.js
First, you'll need to import the component:
tutorial-03-component/src/App.js
import React from 'react'; import Instructions from './Instructions'; import './App.css'; ... export default App;
Since it's the default import, you could import to any name you wanted. It's best to keep the names consistent for readability—the import should match the component name, which should match the file name—but the only firm rule is that the component must start with a capital letter. That's how React knows it's a React component.
Now that you've imported the component, add it to the rest of your code as if it were a custom HTML element:
tutorial-03-component/src/App.js
import React from 'react'; import Instructions from './Instructions.js' ... function App() { const greeting = "greeting"; const displayAction = false; return( <div className="container"> <h1 id={greeting}>Hello, World</h1> {displayAction && <p>I am writing JSX</p>} <Instructions /> <ul> { emojis.map(emoji => ( <li key={emoji.name}> <button onClick={displayEmojiName} > <span role="img" aria-label={emoji.name} id={emoji.name}>{emoji.emoji}</span> </button> </li> )) } </ul> </div> ) } export default App;
In this code, you wrapped the component with angle brackets. Since this component doesn't have any children, it can be self closing by ending with />
.
Save the file. When you do, the page will refresh and you'll see the new component.
Now that you have some text, you can add an image. Download an emoji image from wikimedia and save it in the src
directory as emoji.svg
with the following command:
- curl -o src/emoji.svg https://upload.wikimedia.org/wikipedia/commons/3/33/Twemoji_1f602.svg
curl
makes the request to the URL, and the -o
flag allows you to save the file as src/emoji.svg
.
Next, open your component file:
- nano src/Instructions.js
Import the emoji and add it to your custom component with a dynamic link:
tutorial-03-component/src/Instructions.js
import React, { Component } from 'react'; import emoji from './emoji.svg' export default class Instructions extends Component { render() { return( <> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </> ) } }
Notice that you need to include the file extension .svg
when importing. When you import, you are importing a dynamic path that is created by webpack when the code compiles. For more information, refer to How To Set Up a React Project with Create React App.
You also need to wrap the <img>
and <p>
tags with empty tags to ensure that you are returning a single element.
Save the file. When you reload, the image will be very large compared to the rest of the content:
To make the image smaller, you'll need to add some CSS and a className
to your custom component.
First, in Instructions.js
, change the empty tags to a div and give it a className
of instructions
:
tutorial-03-component/src/Instructions.js
import React, { Component } from 'react'; import emoji from './emoji.svg' export default class Instructions extends Component { render() { return( <div className="instructions"> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </div> ) } }
Save and close the file. Next open App.css
:
- nano src/App.css
Create rules for the .instructions
class selector:
tutorial-03-component/src/App.css
.container { display: flex; flex-direction: column; align-items: center; } ... .instructions { display: flex; flex-direction: column; align-items: center; }
When you add a display
of flex
styling, you make the img
and the p
centered with flexbox. You changed the direction so that everything lines up vertically with flex-direction: column;
. The line align-items: center;
will center the elements on the screen.
Now that your elements are lined up, you need to change the image size. Give the img
inside the div
a width
and height
of 100px
.
tutorial-03-component/src/App.css
.container { display: flex; flex-direction: column; align-items: center; } ... .instructions { display: flex; flex-direction: column; align-items: center; } .instructions img { width: 100px; height: 100px; }
Save and close the file. The browser will reload and you'll see the image is much smaller:
At this point, you've created an independent and reusable custom component. To see how it's reusable, add a second instance to App.js
.
Open App.js
:
- nano src/App.js
In App.js
, add a second instance of the component:
tutorial-03-component/src/App.js
import React from 'react'; import Instructions from './Instructions.js' ... function App() { const greeting = "greeting"; const displayAction = false; return( <div className="container"> <h1 id={greeting}>Hello, World</h1> {displayAction && <p>I am writing JSX</p>} <Instructions /> <Instructions /> <ul> { emojis.map(emoji => ( <li key={emoji.name}> <button onClick={displayEmojiName} > <span role="img" aria-label={emoji.name} id={emoji.name}>{emoji.emoji}</span> </button> </li> )) } </ul> </div> ) } export default App;
Save the file. When the browser reloads, you'll see the component twice.
In this case, you wouldn't want two instances of Instructions
, but you can see that the component can be efficiently reused. When you create custom buttons or tables, you will likely use them multiple times on one page, making them perfect for custom components.
For now, you can delete the extra image tag. In your text editor, delete the second <Instructions />
and save the file:
tutorial-03-component/src/App.js
import React from 'react'; import Instructions from './Instructions.js' ... function App() { const greeting = "greeting"; const displayAction = false; return( <div className="container"> <h1 id={greeting}>Hello, World</h1> {displayAction && <p>I am writing JSX</p>} <Instructions /> <ul> { emojis.map(emoji => ( <li key={emoji.name}> <button onClick={displayEmojiName} > <span role="img" aria-label={emoji.name} id={emoji.name}>{emoji.emoji}</span> </button> </li> )) } </ul> </div> ) } export default App;
Now you have a reusable, independent component that you can add to a parent component multiple times. The structure you have now works for a small number of components, but there is a slight problem. All of the files are mixed together. The image for <Instructions>
is in the same directory as the assets for <App>
. You also are mixing the CSS code for <App>
with the CSS for <Instructions>
.
In the next step, you'll create a file structure that will give each component independence by grouping their functionality, styles, and dependencies together, giving you the ability to move them around as you need.
Step 3 — Creating a Readable File Structure
In this step, you'll create a file structure to organize your components and their assets, such as images, CSS, and other JavaScript files. You'll be grouping code by component, not by asset type. In other words, you won't have a separate directory for CSS, images, and JavaScript. Instead you'll have a separate directory for each component that will contain the relevant CSS, JavaScript, and images. In both cases, you are separating concerns.
Since you have an independent component, you need a file structure that groups the relevant code. Currently, everything is in the same directory. List out the items in your src
directory:
- ls src/
The output will show that things are getting pretty cluttered:
Output
App.css Instructions.js index.js App.js emoji.svg serviceWorker.js App.test.js index.css setupTests.js
You have code for the <App>
component (App.css
, App.js
, and App.test.js
) sitting alongside your root component (index.css
and index.js
) and your custom component Instructions.js
.
React is intentionally agnostic about file structure. It does not recommend a particular structure, and the project can work with a variety of different file hierarchies. But we recommend to add some order to avoid overloading your root directory with components, CSS files, and images that will be difficult to navigate. Also, explicit naming can make it easier to see which pieces of your project are related. For example, an image file named Logo.svg
may not clearly be part of a component called Header.js
.
One of the simplest structures is to create a components
directory with a separate directory for each component. This will allow you to group your components separately from your configuration code, such as serviceWorker
, while grouping the assets with the components.
Creating a Components
Directory
To start, create a directory called components
:
- mkdir src/components
Next, move the following components and code into the directory: App.css
, App.js
, App.test.js
, Instructions.js
, and emoji.svg
:
- mv src/App.* src/components/
- mv src/Instructions.js src/components/
- mv src/emoji.svg src/components/
Here, you are using a wildcard (*
) to select all files that start with App.
.
After you move the code, you'll see an error in your terminal running npm start
.
Output
Failed to compile. ./src/App.js Error: ENOENT: no such file or directory, open 'your_file_path/tutorial-03-component/src/App.js'
Remember, all of the code is importing using relative paths. If you change the path for some files, you'll need to update the code.
To do that, open index.js
.
- nano src/index.js
Then change the path of the App
import to import from the components/
directory.
tutorial-03-component/src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './components/App'; import * as serviceWorker from './serviceWorker'; ... serviceWorker.unregister();
Save and close the file. Your script will detect the changes and the error will disappear.
Now you have components in a separate directory. As your applications become more complex, you may have directories for API services, data stores, and utility functions. Separating component code is the first step, but you still have CSS code for Instructions
mixed in the App.css
file. To create this logical separation, you will first move the components into separate directories.
Moving Components to Individual Directories
First, make a directory specifically for the <App>
component:
- mkdir src/components/App
Then move the related files into the new directory:
- mv src/components/App.* src/components/App
When you do you'll get a similar error to the last section:
Output
Failed to compile. ./src/components/App.js Error: ENOENT: no such file or directory, open 'your_file_path/tutorial-03-component/src/components/App.js'
In this case, you'll need to update two things. First, you'll need to update the path in index.js
.
Open the index.js
file:
- nano src/index.js
Then update the import path for App to point to the App
component in the App
directory.
tutorial-03-component/src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './components/App/App'; import * as serviceWorker from './serviceWorker'; ... serviceWorker.unregister();
Save and close the file. The application still won't run. You'll see an error like this:
Output
Failed to compile. ./src/components/App/App.js Module not found: Can't resolve './Instructions.js' in 'your_file_path/tutorial-03-component/src/components/App'
Since <Instructions>
is not on the same directory level as the <App>
component, you'll need to change the import path. Before that, create a directory for Instructions
. Make a directory called Instructions
in the src/components
directory:
- mkdir src/components/Instructions
Then move Instructions.js
and emoji.svg
into that directory:
- mv src/components/Instructions.js src/components/Instructions
- mv src/components/emoji.svg src/components/Instructions
Now that the Instructions
component directory has been created, you can finish updating the file paths to connect your component to your app.
Updating import
Paths
Now that components are in individual directories, you can adjust the import path in App.js
.
Open App.js
:
- nano src/components/App/App.js
Since the path is relative, you'll need to move up one directory—src/components
—then into the Instructions
directory for Instructions.js
, but since this is a JavaScript file, you don't need the final import.
tutorial-03-component/src/components/App/App.js
import React from 'react'; import Instructions from '../Instructions/Instructions.js'; import './App.css'; ... export default App;
Save and close the file. Now that your imports are all using the correct path, you're browser will update and show the application.
Note: You can also call the root file in each directory index.js
. For example, instead of src/components/App/App.js
you could create src/components/App/index.js
. The advantage to this is that your imports are slightly smaller. If the path points to a directory, the import will look for an index.js
file. The import for src/components/App/index.js
in the src/index.js
file would be import ./components/App
. The disadvantage of this approach is that you have a lot of files with the same name, which can make it difficult to read in some text editors. Ultimately, it's a personal and team decision, but it's best to be consistent.
Separating Code in Shared Files
Now each component has its own directory, but not everything is fully independent. The last step is to extract the CSS for Instructions
to a separate file.
First, create a CSS file in src/components/Instructions
:
- touch src/components/Instructions/Instructions.css
Next, open the CSS file in your text editor:
- nano src/components/Instructions/Instructions.css
Add in the instructions CSS that you created in an earlier section:
tutorial-03-component/src/components/Instructions/Instructions.css
.instructions { display: flex; flex-direction: column; align-items: center; } .instructions img { width: 100px; height: 100px; }
Save and close the file. Next, remove the instructions CSS from src/components/App/App.css
.
- nano src/components/App/App.css
Remove the lines about .instructions
. The final file will look like this:
tutorial-03-component/src/components/App/App.css
.container { display: flex; flex-direction: column; align-items: center; } button { font-size: 2em; border: 0; padding: 0; background: none; cursor: pointer; } ul { display: flex; padding: 0; } li { margin: 0 20px; list-style: none; padding: 0; }
Save and close the file. Finally, import the CSS in Instructions.js
:
- nano src/components/Instructions/Instructions.js
Import the CSS using the relative path:
tutorial-03-component/src/components/Instructions/Instructions.js
import React, { Component } from 'react'; import './Instructions.css'; import emoji from './emoji.svg' export default class Instructions extends Component { render() { return( <div className="instructions"> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </div> ) } }
Save and close the file. Your browser window will look as it did before, except now all the file assets are grouped in the same directory.
Now, take a final look at the structure. First, the src/
directory:
- ls src
You have the root component index.js
and the related CSS index.css
next to the components/
directory and utility files such as serviceWorker.js
and setupTests.js
:
Output
components serviceWorker.js index.css setupTests.js index.js
Next, look inside components
:
- ls src/components
You'll see a directory for each component:
Output
App Instructions
If you look inside each component, you'll see the component code, CSS, test, and image files if they exist.
- ls src/components/App
Output
App.css App.js App.test.js
- ls src/components/Instructions
Output
Instructions.css Instructions.js emoji.svg
At this point, you've created a solid structure for your project. You moved a lot of code around, but now that you have a structure, it will scale easier.
This is not the only way to compose your structure. Some file structures can take advantage of code splitting by specifying a directory that will be split into different packages. Other file structures split by route and use a common directory for components that are used across routes.
For now, stick with a less complex approach. As a need for another structure emerges, it's always easier to move from simple to complex. Starting with a complex structure before you need it will make refactoring difficult.
Now that you have created and organized a class-based component, in the next step you'll create a functional component.
Step 4 — Building a Functional Component
In this step, you'll create a functional component. Functional components are the most common component in contemporary React code. These components tend to be shorter, and unlike class-based components, they can use React hooks, a new form of state and event management.
A functional component is a JavaScript function that returns some JSX. It doesn't need to extend anything and there are no special methods to memorize.
To refactor <Instructions>
as a functional component, you need to change the class to a function and remove the render method so that you are left with only the return statement.
To do that, first open Instructions.js
in a text editor.
- nano src/components/Instructions/Instructions.js
Change the class
declaration to a function
declaration:
tutorial-03-component/src/components/Instructions/Instructions.js
import React, { Component } from 'react'; import './Instructions.css'; import emoji from './emoji.svg' export default function Instructions() { render() { return( <div className="instructions"> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </div> ) } }
Next, remove the import of { Component }
:
tutorial-03-component/src/components/Instructions/Instructions.js
import React from 'react'; import './Instructions.css'; import emoji from './emoji.svg' export default function Instructions() { render() { return( <div className="instructions"> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </div> ) } }
Finally, remove the render()
method. At that point, you are only returning JSX.
tutorial-03-component/src/components/Instructions/Instructions.js
import React from 'react'; import './Instructions.css'; import emoji from './emoji.svg' export default function Instructions() { return( <div className="instructions"> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </div> ) }
Save the file. The browser will refresh and you'll see your page as it was before.
You could also rewrite the function as an arrow function using the implicit return. The main difference is that you lose the function body. You will also need to first assign the function to a variable and then export the variable:
tutorial-03-component/src/components/Instructions/Instructions.js
import React from 'react'; import './Instructions.css'; import emoji from './emoji.svg' const Instructions = () => ( <div className="instructions"> <img alt="laughing crying emoji" src={emoji} /> <p>Click on an emoji to view the emoji short name.</p> </div> ) export default Instructions;
Simple functional components and class-based components are very similar. When you have a simple component that doesn't store state, it's best to use a functional component. The real difference between the two is how you store a component's state and use properties. Class-based components use methods and properties to set state and tend to be a little longer. Functional components use hooks to store state or manage changes and tend to be a little shorter.
Conclusion
Now you have a small application with independent pieces. You created two major types of components: functional and class. You separated out parts of the components into directories so that you could keep similar pieces of code grouped together. You also imported and reused the components.
With an understanding of components, you can start to look at your applications as pieces that you can take apart and put back together. Projects become modular and interchangable. The ability to see whole applications as a series of components is an important step in thinking in React. If you would like to look at more React tutorials, take a look at our React Topic page, or return to the How To Code in React.js series page.
How To Create A Component In React
Source: https://www.digitalocean.com/community/tutorials/how-to-create-custom-components-in-react
Posted by: milsapmustrien.blogspot.com
0 Response to "How To Create A Component In React"
Post a Comment