Code Monkey home page Code Monkey logo

react-hooks-props-destructuring's Introduction

Props Destructuring and Default Values

Overview

We'll cover props in further detail and explore how they help us make our components more dynamic and reusable. We'll also talk about destructuring and how to give our props default values.

Objectives

  1. Explain how props make our components more dynamic and reusable
  2. Pass props to a component by adding them as attributes when you render them
  3. Use destructuring to access props more easily
  4. Declare default values for destructured props
  5. Render a component with props and default props

Reviewing What We Know

Props allow us to pass values into our components. These values can be anything: strings, objects (including arrays and functions), and so on. They give us the opportunity to make our components more dynamic, and a lot more reusable.

For example, say we have a <MovieCard /> component. A movie has a title, a poster image, and many other attributes (or prop-erties!). Let's examine what this <MovieCard /> component would look like with hardcoded, static data vs. dynamic prop data:

Hardcoded with Static Data:

function MovieCard {
  return (
    <div className="movie-card">
      <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTn1OTYGz2GDC1XjA9tirh_1Rd571yE5UFIYsmZp4nACMd7CCHM" alt="Mad Max: Fury Road" />
      <h2>Mad Max: Fury Road</h2>
      <small>Genres: Action, Adventure, Science Fiction, Thriller</small>
    </div>
  )
}

Passing in props

Mad Max: Fury Road is a ridiculously good movie, but what if we want to render a movie card for another movie? Do we just write another component? No, that would be silly! Instead, we write our components so that they make use of props, which are passed from their parents.

To pass props to a component, you add them as attributes when you render them, just like adding attributes to a HTML element:

const movieTitle = "Mad Max"
<MovieCard title={movieTitle} />

The value of a prop is passed in through JSX curly braces. As we read before, this value can be anything: a variable, inline values, functions, etc. If your value is a hardcoded string, you can pass it in through double quotes instead:

<MovieCard title="Mad Max" />

Armed with that knowledge, let's update MovieCards render method to make use of props:

Dynamic with Props:

// parent component
function App() {
  const title = "Mad Max";
  const posterURL =
    "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTn1OTYGz2GDC1XjA9tirh_1Rd571yE5UFIYsmZp4nACMd7CCHM";
  const genresArr = ["Action", "Adventure", "Science Fiction", "Thriller"];

  return (
    <div className="App">
      {/* passing down props from the parent component */}
      <MovieCard title={title} posterSrc={posterURL} genres={genresArr} />
    </div>
  );
}

// child component
function MovieCard(props) {
  return (
    <div className="movie-card">
      <img src={props.posterSrc} alt={props.title} />
      <h2>{props.title}</h2>
      <small>{props.genres.join(", ")}</small>
    </div>
  );
}

Now, does that not look cleaner and more reusable compared to our hard coded example or what!?

Destructuring Props

Since we know that a React function will only every get called with one argument, and that argument will be the props object, we can take advantage of a modern JavaScript feature called destructuring to make our component even cleaner:

function MovieCard({ title, posterSrc, genres }) {
  return (
    <div className="movie-card">
      <img src={posterSrc} alt={title} />
      <h2>{title}</h2>
      <small>{genres.join(", ")}</small>
    </div>
  );
}

In this example, we're destructuring the props argument in this function, which will have title, posterSrc, and genres as keys. Destructuring allows us to take the keys from the props object and assign them to variables with the same name. That way, in our JSX, we don't have to use props.whatever everywhere - we can just access the value directly!

Another benefit of destructuring props is that it makes it easier to tell what props a component expects to be passed down from its parent. Consider these two versions of the same component:

// Without Destructuring
function MovieCard(props) {
  return (
    <div className="movie-card">
      <img src={props.posterSrc} alt={props.title} />
      <h2>{props.title}</h2>
      <small>{props.genres.join(", ")}</small>
    </div>
  );
}

// With Destructuring
function MovieCard({ title, posterSrc, genres }) {
  return (
    <div className="movie-card">
      <img src={posterSrc} alt={title} />
      <h2>{title}</h2>
      <small>{genres.join(", ")}</small>
    </div>
  );
}

Looking at the version without destructuring, we'd have to find all the places where props is referenced in the component to determine what props this component expects. Looking at the version with destructuring, all we have to do is examine the function parameters and we can see exactly what props the component needs!

Destructuring Nested Objects

We can also do some more advanced destructuring in cases when our props also contain nested objects. For example:

function App() {
  const socialLinks = {
    github: "https://github.com/liza",
    linkedin: "https://www.linkedin.com/in/liza/",
  };

  return (
    <div>
      <SocialMedia links={socialLinks} />
    </div>
  );
}

function SocialMedia({ socialLinks }) {
  return (
    <div>
      <a href={socialLinks.github}>{socialLinks.github}</a>
      <a href={socialLinks.linkedin}>{socialLinks.linkedin}</a>
    </div>
  );
}

Since socialLinks is an object, we can also destructure it to make our JSX cleaner, either by destructuring in the body of the function:

function SocialMedia({ socialLinks }) {
  const { github, linkedin } = socialLinks;

  return (
    <div>
      <a href={github}>{github}</a>
      <a href={linkedin}>{linkedin}</a>
    </div>
  );
}

...or by destructuring further in the parameters to our function:

function SocialMedia({ socialLinks: { github, linkedin } }) {
  return (
    <div>
      <a href={github}>{github}</a>
      <a href={linkedin}>{linkedin}</a>
    </div>
  );
}

How much destructuring you do, and where you do it, is very much a matter of preference. Try it out in some components and see what feels right to you!

Default Values for Props

Let's switch gears here and imagine we are using our application to render a list of hundreds of movies. Let's also assume the data set we have is not always reliable when it comes to the urls of the movie posters.

In this case, we want to make sure our component doesn't render as an utter disaster when the data is incomplete. In order to do this, we can use a default value to assign a poster url when either a bad one, or none at all, is provided. For this example, let's use the poster for Max Headroom as a default, seeing as it is a perfect placeholder:

max headroom poster

Instead of passing in that default poster image in case we don't have one, we can tell our MovieCard component to use a default value if the posterSrc prop was not provided. To do this, we can add default value to our destructured props:

function MovieCard({
  title,
  genres,
  posterSrc = "https://m.media-amazon.com/images/M/MV5BOTJjNzczMTUtNzc5MC00ODk0LWEwYjgtNzdiOTEyZmQxNzhmXkEyXkFqcGdeQXVyNzMzMjU5NDY@._V1_UY268_CR1,0,182,268_AL_.jpg",
}) {
  return (
    <div className="movie-card">
      <img src={posterSrc} alt={title} />
      <h2>{title}</h2>
      <small>{genres.join(", ")}</small>
    </div>
  );
}

Now, whenever we omit the posterSrc prop, or if it's undefined, the MovieCard component will use this default value instead. That means we don't have to worry about not passing in a poster all the time โ€” the component will take care of this for us!

For example, this version of our component would still display its default image, even though we aren't passing a prop of posterSrc from the parent component:

function App() {
  const title = "Mad Max";
  const genresArr = ["Action", "Adventure", "Science Fiction", "Thriller"];

  return (
    <div className="App">
      {/* posterSrc is omitted, so the default value will be used instead */}
      <MovieCard title={title} genres={genresArr} />
    </div>
  );
}

Why Use Default Values

An alternative way we could have handled bad urls would be to have MovieCard's parent component check whether the posterSrc was valid/present, and then pass some control value as a prop when it renders MovieCard. This is not ideal compared to using a default prop within the MovieCard component.

Consider the following: in React, we want components to encapsulate the functionality that they can and should be responsible for. Should the parent component of MovieCard be responsible for managing the assignment of a default movie poster source value? In our example, we think not. It makes more sense for the component that is responsible for rendering the movie information and poster to handle missing data.

Summary

By using destructuring in our components, we can make the returned JSX elements easier to read, because we don't need to reference props.whatever everywhere. Destructuring also makes it easier to tell what props a component expects, since we can just look at the destructured parameters instead of reading through the whole component and looking for references to the props object.

When we use destructuring, we can provide a default value for any prop keys we want, so that if the component doesn't receive those props from its parents, we can still render some default information.

Resources

react-hooks-props-destructuring's People

Contributors

danielseehausen avatar ihollander avatar kel29 avatar rrcobb avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.