Anatomy of a React Component


Previous post: Anatomy of a React App
Next post: JSX
Next section: The Basics


Anatomy of a React App

So in the previous tutorial (Anatomy of a React App: https://scattercode.blogspot.com/2022/11/anatomy-of-react-app.html) we saw what makes up a React App, but part of that explanation was that it "creates and shows an App Component", which is perhaps not as detailed an explanation as you were hoping for. In this tutorial we'll see what a Component actually is, and how to create one.


The App Component

The basic starting block for our app is the App component, which is made by create-react-app and saved in App.js. In theory you can rename this to anything else (as long as you update the corresponding references in index.js), but there usually isn't any good reason to do that, and it'll end up confusing things, so we're not going to.

Initially, as long as we've used create-react-app to set everything up, App.js contains the following (or something like it; this file changes from time to time):

    import logo from "./logo.svg";
    import "./App.css";

    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>Edit <code>src/App.js</code> and save to reload.</p>
            <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer">Learn React</a>
          </header>
        </div>
      );

    }

    export default App;

Feel free to play about with the part inside the return () (don't mess with anything else for now). When you make a change and then save the file, the browser will automatically refresh and you'll see your change on the screen (just make sure you're outputting valid HTML).

NOTE: For editing files, I generally use VSCode , which has lots of good features, such as being free. You can also use something like Notepad++ on Windows, or TextEdit on MacOS, or really any kind of text editor you're familiar with, but VSCode is specifically a code editor and therefore has a bit more of an idea of what you're trying to do, so it can do things like highlighting code errors, formatting your code etc. 

To open your project in VSCode, first open VSCode itself, and then go to File > Open..., navigate to your project folder (that's the one that contains package.json and the src folder) and click 'Open'.

App is a basic example of a React component.  A React component is just a Javascript function which returns JSX (JSX looks a bit like HTML but it can also handle Javascript, as we'll see shortly). As with any function, we can pass in parameters.

Crucially, components in React can pull in other components.  So if you're building an app,  rather than building the entire thing in App.js, you'll split it down into smaller and smaller components, and build it up from those.

So, for example, if your app is going to have several screens (say, a Home screen, a My Account screen and a Preferences screen), each of those would probably be a separate component (each in a separate file), and then the App component will check the url of the current screen* and display the appropriate one.

(* it's a bit more complicated than 'check the url of the current screen' but that's the basic idea)

Then, let's say your Home screen has your app logo at the top, then a list of some kind - let's say books you've read - and then a button to add a new book.  In this case you'd probably create something like a Header component (which gets put at the top of every screen), a Button component, and a BookItem component.  The BookItem component would display the details for a single book; for your list, you then show lots of BookItems.

If you then decide to have another screen which shows your friends' books, you can create that easily using the same Header and BookItems, but with different content - you've got the building blocks already.


A Basic Component

A React component has just a few essential features:

1. It has to have a name, and that name has to start with a capital letter. Obviously it's advisable to give it a name that describes what the component does (eg ProfilePhoto or FurtherInfo), but if you enjoy rampant confusion and want to call it H5j1pO6, don't let me stop you. It's also conventional to use PascalCase, which means that every 'word' in the name gets a capital letter, so if your component shows the user's profile information, you might call it UserProfileInfo.

2. A return method, which uses JSX to describe what should be shown.  Sometimes you don't want to show anything (for example, maybe you want to hide a 'Book Now' button when there are no available appointments); in this case you can return <></>, which is basically JSX for 'show nothing'.

3. An export, if you want to use this component within other components.  By putting 'export', you are saying that this component can be used by components in other files.

If you're not familiar with how imports and exports work in JavaScript, you can have a look at this brief overview.

Likewise, if you're getting confused by the various ways of writing a JavaScript function, check out this guide.

So, the most basic React component would be something like this:

    const App = () => {
      return <></>;
    }

    export default App;

or, the same thing using implicit return shorthand:

    export default () => <></>;

which just returns nothing (you can see this if you change App.js to this - your browser will show an empty screen. If you look at the source code - you'll see that the root div is empty).

If we wanted to show 'Hello, World', we could do it like this:

    const App = () => {
      return <h1>Hello, World</h1>;
    }
    export default App;

or, again, in implicit return shorthand:

    export default () => <h1>Hello, World</h1>;

Of course, most components are considerably more complex than this.  We can pass in parameters, or read information from a database, or ask the user to enter something, and then return different output based on the information we've got. 


The Component Tree

Components are generally thought of as being structured like a family tree (called the Component Tree).  The App component is the root, and then it can have various child components; each of those can have their own child components and so on. Look at the example below, which shows a simple dashboard screen:




Think about the structure of this screen.

Firstly, we could split it into 2 components - the navigation bar and the main screen.  Let's call them NavBar and MainScreen.

Then, if we look at NavBar, we can split it into Logo followed by Navigation. Then we can break down Navigation into individual MenuItems.

So the component tree for this screen might look like this (you can name the components anything you like; I'm just listing what I would probably call them):

    App
    - NavBar
      -- Logo
      -- Navigation
         --- MenuItem (Home)
         --- MenuItem (Messages)
         --- MenuItem (Stats)
         --- MenuItem (Users)
         --- MenuItem (Sign Out)
    - MainScreen
      -- WelcomeMessage
      -- SinceLastSignInBox
      -- CurrentUsersBox

Note that this is not the only way to draw the component tree here.  You may find that you want to split SinceLastSignInBox into SinceLastSignInWelcome, SinceLastSignInMessages, and SinceLastSignInUsers.  Or you might want the WelcomeMessage to just be part of the MainScreen component, rather than a separate one.  It's largely a case of personal preference and, if you're working for someone else, company style guides.

Once you've designed your screen, it's worth drawing out a component tree so that you can get an idea of how you'll build the app, and which components you're going to need.  You might decide that some components are basically the same thing - for example, in the screen above, the two components which say 'Welcome to your dashboard' and 'Since your last login, you have' are both just blue static text.  So for these it might be better to define a Heading component which takes a string of text and styles it in blue, and then pass the specific text in when we want to use it.

When describing the component tree, we say that App has 2 children (NavBar and MainScreen).  MainScreen has 3 children (WelcomeMessage, SinceLastSignInBox and CurrentUserBox).  Conversely, MainScreen's parent is App.

So a component can have multiple children, but can only have one parent.

Additionally, the parent can pass information down to children, but children cannot pass information directly to a parent (there is a way of doing it indirectly, which we'll come to eventually).

NOTE: there's no point getting carried away with defining these relationships; as long as we have a basic grasp of how Parent and Child relate to each other.  Generally React doesn't go as far as talking about 'grandparent' components, but if someone said it we'd know what they meant.

Using A Child Component

To use a child component in App, we simply define it, import it and use it.  We'll do these 3 steps with a component which we'll call HelloWorldHelloWorld will just show the message "Hello World".

Before we start, make sure that App.js contains the following (so if you've been messing around with it, delete everything and replace it with this):

    const App = () => {
      return <></>;
    }

Step 1: Define

Now we'll define our new component.  Create a new file in the same directory as App.js, and call it HelloWorld.js.

There are no real rules for folder and file names in React; you can put files anywhere within src, and you can call them whatever you want.  As this example only has 2 small files, I've put them in the same directory, but for bigger projects we'll be a bit more organised.

In HelloWorld.js, we'll define a component called HelloWorld:

    const HelloWorld = () => { 
        return <h1>Hello World</h1>;
    }
    export default HelloWorld;

So this is basically the same as App.js from earlier - it just returns an h1 header which says 'Hello World'. Note that we've included an export, so that the component can be imported by App. Save this file.

Step 2: Import

Now we need to import HelloWorld into App.js so that we can use it.

In App.js, add the following line to the top of the file (if you're using VSCode, it will probably auto-complete the import when you start typing HelloWorld):

    import HelloWorld from "./HelloWorld";

Step 3: Use

Finally, we want to use the HelloWorld component in App.js.

Change the return statement of App.js to this:

    return <HelloWorld />;

Now save the file and take a look at the output in your browser.  It should say 'Hello World' in big letters.


Conclusion

So now you can create a component tree for your app, and generate a list of the components you're going to need to create.  Once you've done this, it's more or less a case of creating the components one-by-one, and slotting them into the correct place*.

(* There's a bit more to be said about slotting them in, and we'll get to that soon)




Previous post: Anatomy of a React App

Next post: JSX
Next section: The Basics

Comments