Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

React Guide to Props - Part I

DZone's Guide to

React Guide to Props - Part I

In this post, an intrepid web developer guides us safely through the complex terrain of props in the React framework. Tally-ho!

· Web Dev Zone ·
Free Resource

Learn how error monitoring with Sentry closes the gap between the product team and your customers. With Sentry, you can focus on what you do best: building and scaling software that makes your users’ lives better.

Disclaimer: This was intended to be part III of React JSX series, but as for props there's a lot to be covered, so we have decided to divide it into a subseries!

In some of our previous articles, you had the opportunity to read about JSX specific stuff, like how to render content in loops and how to do conditional rendering in React.

Today, you will learn how props function. However, before we move to actual prop usage examples, you must first understand the difference between state, props, and refs. Once you know what these are, everything will be a lot easier. Here's a short explanation:

The state is similar to attributes in object-oriented programming: it's something local to a class (component), used to better describe it. We'll cover React state management and what should be kept in the local state in another article.

Props are like parameters - they are passed to a component from the caller of a component (the parent): as if you called a function with certain parameters.

Refs are, as the name suggests, references to nested components (children), used for functionality like triggering of focus or an animation. However, they shouldn't be used too much, as the most proper way to communicate between the components is via props.

Now that we have covered all the basic differences, we can start with the prop passing!

All of the below applies to React Native as well!

Passing Props - the Standard Way

Passing props is pretty straightforward: you send a prop by specifying the name under which will it be available in a child component and defining what the prop should equal:

render() {
    return (
        <Child
            propName={propValue}
        />
    )
}

Here is a more realistic example:

render() {
    // strings don't have to be wrapped with {},
    // but it's better to get used to wrapping everything
    return (
        <Movie
            actors={[
                ...
            ]}
            details={{
                director: "Director name",
                ...
            }}
            duration={120}
            released={true}
            title={"Movie title"}
        />
    )
}

That's basically it for sending a prop! Below you'll find some more specific props you'll definitely be using at some point when coding in React!

Boolean Props

If you want to pass a true value as a prop, you can do it like this:

render() {
    // No need for "released={true}"!
    return (
        <Movie
            released
        />
    )
}

In the same manner, if you want to pass a false value, you can do it by just not passing anything at all:

render() {
    // This will work the same way as if you passed "released={false}"!
    return (
        <Movie />
    )
}

If the boolean value is contained within a variable, then, of course, you'll have to pass it.

render() {
    let booleanVariable = true; // this will often be calculated
    return (
        <Movie
            released={booleanVariable}
        />
    )
}

You can directly calculate the value of a prop when passing it, as well:

render() {
    return (
        <Movie
            released={value1===value2}
        />
    )
}

Just keep in mind that it should be clear what's happening in the code, if the expression is too long, move it above the return statement or even to a separate function:

isFormValid() {
    // various checks, whether every form field is of correct format
}
render() {
    return (
        <Form
            disabled={!this.isFormValid()}
            fields={this.state.fields}
        />
    )
}

Function Props

Often, you'll have to pass functions and event handlers as props. The functions you pass need to be bound to the component context. However, don't bind functions in render methods:

handleChange(event) {
    // do something here
}

render() {
    return (
        <div>
            {
                // don't do this!
            }
            <input
                onChange={this.handleChange.bind(this)}
            />
        </div>
    )
}

If you bind a function in render, everytime a component is rerendered, a new function will be created. Instead, it's the best to use the arrow syntax when defining a function (you'll need Babel configured to use ES6 syntax!).

handleChange = (event) => {
    // do something here
}

render() {
    return (
        <div>
            <input
                onChange={this.handleChange}
            />
        </div>
    )
}

You might be thinking: that's fine when there are no other parameters to be passed, but what if I need to pass an attribute? Here's how to do it with arrow functions:

handleChange = (parameter1, parameter2) => (event) => {
    // do something here
}

render() {
    return (
        <div>
            <input
                onChange={this.handleChange(parameter1, parameter2)}
            />
        </div>
    )
}

Sending Props to this.props.children

Sending the props to a child component called directly in the code is pretty straightforward, but how do we send the props to children passed as a prop?

This is the way to do it:

render() {
    let updatedChildren = React.Children.map(this.props.children,
        (child) => {
            return React.cloneElement(child, { newProp: newProp });
        });

    return (
        <div>
            { updatedChildren }
        </div>
    );
}

If your component has just one child, there's no need for mapping, so you can do this as well:

render() {
    return (
        <div>
            {
                React.cloneElement(this.props.children, {
                    newProp: newProp
                })
            }
        </div>
    );
}

Props and the '...'

You might have seen the three dots earlier and wondered what they mean. Code similar to the next example is quite common in React world:

render() {
    return (
        <Movie
            {...this.props}
        >
    );
}

The ... is a spread operator, and it'll send each of the key-value pairs inside of this.props as a separate prop to the Movie component. Let's say that we have an object called movie:

const movie = {
    title: "Inception",
    releaseDate: "16.07.2010",
    genre: [
        "Action", "Adventure", "Sci-Fi",
    ],
};

We should pass all of the key-value pairs from the movie object to the Movie component. Here's how we'd do it without the ...:

render() {
    return (
        <Movie
            title={movie.title}
            releaseDate={movie.releaseDate}
            genre={movie.genre}
        />
    );
}

Now, the code above can be much shorter using the three dots syntax, and work completely the same:

render() {
    return (
        <Movie {...movie} />
    );
}

However, although it's way shorter, it can get a bit messy over time, so don't overuse it! Also, keep in mind, that although the ... works as a spread operator for arrays as well, when sending props you should only use it on objects!

Thank you for your time!

Now that we've gone through the prop basics, you can make your components communicate and better understand how they do so!

This, however, is just the beginning, as there's a lot more to learn about component communication.

What’s the best way to boost the efficiency of your product team and ship with confidence? Check out this ebook to learn how Sentry's real-time error monitoring helps developers stay in their workflow to fix bugs before the user even knows there’s a problem.

Topics:
web dev ,react.js ,javascript ,web application development

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}