DEV Community

Cover image for Understanding Components and Props
Silas
Silas

Posted on

Understanding Components and Props

Table of Contents


Hello again. If you are reading this, you are interested in React. This is the second in the React Introductory series. Check out Introduction to React if you haven't.

Let's continue ...

What are Components

These are, ideally, the smallest building blocks of a page or user interface. They include buttons, input boxes, radio buttons and check boxes etc.
These are what make up a page and are used for data input and user interactions.

Components make use and/or take the syntax of html elements. The html elements include:

<div></div - creates a container
<input type="text"/> - creates an input box
<button>Button</button> - creates a button
...
and so on.

React components, are generally created or defined inside a .jsx file. The definition(or component) must subsequently be exported to make it usable and accessible across the entire app.

In React basic structure, components live inside App-folder/src/components folder.

So, go ahead and create a button component in the component directory. Create a file Button.jsx or whatever you decide to call it, but remember to add the .jsx extension, to tell the compiler that this is a React component.

Inside this file, add the following:

function Button(){
   return(
    <button>I am a Button</button>
)
}
Enter fullscreen mode Exit fullscreen mode

Notice that we did not start with import react from "react".
As from react 18, this has been automated, and the compiler will automatically(behind the scenes), import this package thus allowing you to continue without that particular import directive.

You have now written your first component. However, we are not done yet. Trying to use this will throw an error. But why??
You guessed it right. EXPORT!! We have not exported the function/component.

Exporting Functions and Components

There are 2 ways of exporting. You can:

  • Export as you define the component
  • Export once you are done defining

The only difference between the two is the placement of the export keyword.

export function Button(){
   return(
    <button>I am a Button</button>
)
}
Enter fullscreen mode Exit fullscreen mode

OR

function Button(){
   return(
    <button>I am a Button</button>
)
}

export Button
Enter fullscreen mode Exit fullscreen mode

The above definition is what we call React Function component. There is another definition that uses Arrow Functions.
The layout of an arrow function component looks like this:

export const Button=()=>{
   return(
    <button>I am a Button in an Arrow function</button>
)
}
Enter fullscreen mode Exit fullscreen mode

OR

const Button=()=>{
   return(
    <button>I am a Button in an Arrow function</button>
)
}

export Button
Enter fullscreen mode Exit fullscreen mode

Both definitions of arrow function and native function have slightly different syntax, but the two will give the same expected output

We have now written and exported our first component. To see it in action, open our App.jsx.

To use a component in another component or page, you will need to import it.

import {Button} from "./components/Button.jsx"

function App(){
 return(<Button/>)
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Now save and run npm run dev and open http://localhost:5173 and see our button.

When do we do import { Button } from "./component" and when do we do import Button from "./component"?
TODO : Read about Exports here and be able to tell the difference

Props

Props is short for properties. These are characteristics or definitions unique to an element. Just like attributes in html, props are used to pass data between elements in a page.
Props are passed into a jsx element as arguments of a function.

function Button({onClick,color,width}){
 return(
  <button/>
)
}
Enter fullscreen mode Exit fullscreen mode

Props can be of any data type: e.g string, boolean, number, object or even functions.

But why ({onClick}) instead of (onClick) ??
Well, Every JSX has a default object property attached to it. So when you pass in a property, the property becomes a field in that object.
{onClick} - this uses destructuring to get the actual props

(props) - this uses renames the default props to the name given. To access the actual props, you will have to do props.onClick,props.color and so on.

Props are useful to send data from parent component to child and from child to parent.

It is worth noting that passing a prop from one element to another will be detected by react, and if that prop changes, react will trigger a re-render. When components are deeply nested and one prop has to make way down to n-th level, when the prop is passed from parent to n, this is what would be termed as PROP DRILLING. This causes unnecessary rerenders.
One way to fix this is by using a global store that elements and components can directly access without depending on other components

Let's see these in action:
Create a Car.jsx component in components folder

export const Car=({color,make,model})=>{
    return(
        <span>{make} {model} - {color}</span>
    )
}
Enter fullscreen mode Exit fullscreen mode
import { Car } from "./components/Car.jsx"

function App(){
  return(<Car make={"Toyota"} model={"Tacoma"} color={"Silver"}/>)
}

export default App
Enter fullscreen mode Exit fullscreen mode

Running this should give you something like this:

React example

Props as functions

Let's go through this example. We will, for this one call a function that is residing on the parent from the child.

So, defined our component.
Our component receives a destructured prop,onClick, from the parent.
Our button has an onClick attribute. This defines the event that happens when the button gets clicked. In this case, the onClick will be called.

export const Car=({setClick})=>{
    return(
        <button onClick={setClick}>
    )
}
Enter fullscreen mode Exit fullscreen mode

Now, in the parent component, in our case, App.jsx, we define the function that will get executed when the button in the child component will be clicked.
setClick prop is now set to handleClick function, and this should trigger a console.log("Clicked), which should display a "Clicked" message on the console.

import { Car } from "./components/Car.jsx"
function handleClick(){
   console.log("Clicked")
}
function App(){
  return(<Car setClick={handleClick}/>)
}

export default App
Enter fullscreen mode Exit fullscreen mode

You have successfully passed props between parent and child and executed parent functions from child component.

TODO: Create a child component with a button that will increment a counter on the parent.

Assuming you have done the above, let's go through it.
Create a button component like we did above:

export const Button =({onClick})=>{
     return(
          <button onClick={onClick}>Increment</button>
     )
}
Enter fullscreen mode Exit fullscreen mode

Then in our App.js, let's import and add the button component:

import { Button } from "./components/Button.jsx"

function App(){

function increment(){
   //increment logic will go here
}
  return(
        <div>
          <p>Count:</p>
          <Button onClick={increment}/>
        </div>
     )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Now we will introduce a state manager, useState, to keep track of our state 'count' and rerender the component on change.

import { useState } from "react"
import { Button } from "./components/Button.jsx"

function App(){
//create our state variables
const [count, setCount] = useState(0)

function increment(){
   //increment logic will go here
}
  return(
        <div>
          <p>Count: {count}</p>
          <Button onClick={increment}/>
        </div>
     )
}

export default App
Enter fullscreen mode Exit fullscreen mode

The 0 in useState(0) tells the compiler that count is of type number and the default value is 0. Default values can include objects, strings, booleans, pretty much any data type.

From our previous lesson, you remember how to set state. We want to change the state value everytime the button is clicked.

function increment(){
   setCount((prev)=>prev+1)
}
Enter fullscreen mode Exit fullscreen mode

Now, save everything and run your server.
You should get a Count: 0 and a button Increment. Clicking the button will increment the count value.

Congratulations!! You have used state, passed props and exported components.
Now do the exercise below to challenge yourself even more.

Exercise

Exercise: Create a color changer. A box and an input field. The box will change color to the color specified in the input field.(This introduces you to CSS styling of components as well as what we have gone through).

Happy hacking, see you in the next one!!

Top comments (0)