Passing/Accessing props in stateless child component
Asked Answered
D

8

24

I know you can pass all a react components props to it's child component like this:

const ParentComponent = () => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent {...this.props} />
   </div>
)

But how do you then retrieve those props if the child component is stateless? I know if it is a class component you can just access them as this.prop.whatever, but what do you pass as the argument into the stateless component?

const ChildComponent = ({ *what goes here?* }) => (
   <div>
      <h1>Child Component</h1>
   </div>
)
Dimer answered 23/1, 2017 at 18:28 Comment(2)
Are you working with a functional component or class component?Shutin
Yes - my setup is as I have stated in the original postDimer
A
20

When you write

const ChildComponent = ({ someProp }) => (
   <div>
      <h1>Child Component {someProp}</h1>
   </div>
)

From all the props that you are passing to the childComponent you are just destructuring to get only someProp. If the number of props that you want to use in ChildComponents are countable(few) amongst the total number of props that are available, destructuring is a good option as it provides better readability.

Suppose you want to access all the props in the child component then you need not use {} around the argument and then you can use it like props.someProp

const ChildComponent = (props) => (
   <div>
      <h1>Child Component {props.someProp}</h1>
   </div>
)
Annoying answered 23/1, 2017 at 18:43 Comment(0)
D
11

Are you looking for the ES6 named argument syntax (which is merely destructuring) ?

const ChildComponent = ({ propName }) => (
    <div>
     <h1>Child Component</h1>
 </div>
)

const ChildComponent = (props) => ( // without named arguments
    <div>
     <h1>Child Component</h1>
 </div>
)

Optionally there is a second argument to your function depending of whether you specified a context for your component or not.

Perhaps it would be more helpful wityh a links to the docs. As stated in the first article about functional components. Whatever props passed on to the component is represented as an object passed as first argument to your functional component.

To go a little further, about the spread notation within jsx.

When you write in a component :

<Child prop1={value1} prop2={value2} />

What your component will receive is an plain object which looks like this :

{ prop1: value1, prop2: value2 }

(Note that it's not a Map, but an object with only strings as keys).

So when you're using the spread syntax with a JS object it is effectively a shortcut to this

const object = { key1: value1, key2: value2 }
<Component {...object}/>

Is equivalent to

<Component key1={value1} key2={value2} />

And actually compiles to

return React.createElement(Component, object); // second arg is props

And you can of course have the second syntax, but be careful of the order. The more specific syntax (prop=value) must come last : the more specific instruction comes last.

If you do :

<Component key={value} {...props} />

It compiles to

React.createElement(Component, _extends({ key: value }, props));

If you do (what you probably should)

<Component {...props} key={value} />

It compiles to

React.createElement(Component, _extends(props, { key: value }));

Where extends is *Object.assign (or a polyfill if not present).

To go further I would really recommend taking some time to observe the output of Babel with their online editor. This is very interesting to understand how jsx works, and more generally how you can implement es6 syntax with ES5 tools.

Downtown answered 23/1, 2017 at 18:38 Comment(1)
Actually I'm trying to avoid listing all of the individual props in the parent component as it's verbose. So I want to use the {...this.props} syntax. I just don't know how to access these in the child component.Dimer
P
3

You can use Spread Attributes reducing code bloat. This comes in the form of {'somearg':123, ...props} or {...this.props}, with the former allowing you to set some fields, while the latter is a complete copy. Here's an example with ParentClass.js :

import React from 'react';
import SomeComponent from '../components/SomeComponent.js';

export default class ParentClass extends React.Component {
    render() {
        <SomeComponent
            {...this.props}
        />
    }
}

If I do, <ParentClass getCallBackFunc={() => this.getCallBackFunc()} />, or if I do <ParentClass date={todaysdatevar} />, the props getCallBackFunc or date will be available to the SomeComponent class. This saves me an incredible amount of typing and/or copying/pasting.

Source: ReactJS.org: JSX In Depth, Specifying the React Element Type, Spread Attributes. Official POD:

If you already have props as an object, and you want to pass it in JSX, you can use ... as a “spread” operator to pass the whole props object. These two components are equivalent:

 return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
 const props = {firstName: 'Ben', lastName: 'Hector'};
 return <Greeting {...props} />;
}```

Now, let's apply this to your code sample!

const ParentComponent = (props) => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent {...props} />
   </div>
);
Pneumothorax answered 20/10, 2017 at 15:1 Comment(0)
G
3
const ParentComponent = (props) => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent {...props} />
   </div>
);

const ChildComponent = ({prop1, ...rest}) =>{
  <div>
    <h1>Child Component with prop1={prop1}</h1>
    <GrandChildComponent {...rest} />
  </div>
}

const GrandChildComponent = ({prop2, prop3})=> {
  <div>
    <h1>Grand Child Component with prop2={prop1} and prop3={prop3}</h1>
  </div>
}
Genteel answered 25/10, 2017 at 6:0 Comment(0)
U
1

I thought I would add a simple ES2015, destructuring syntax I use to pass all props from a functional parent to a functional child component.

const ParentComponent = (props) => (
  <div>
    <ChildComponent {...props}/>
  </div>
);

Or if I have multiple objects (props of parent, plus anything else), I want passed to the child as props:

const ParentComponent = ({...props, ...objectToBeAddedToChildAsProps}) => (
  <div>
    <ChildComponent {...props}/>
  </div>
);

This destructuring syntax is similar to the above answers, but it is how I pass props along from functional components, and I think it is really clean. I hope it helps!

Unsteady answered 5/9, 2017 at 17:53 Comment(0)
S
0

But how do you then retrieve those props if the child component is stateless?

const ChildComponent = ({ *what goes here?* }) => (
   <div>
      <h1>Child Component</h1>
   </div>
)

ChildComponent holds the name and the props will be the argument in the arrow function syntax just as you need:

 const ChildComponent = props => (
   <div>
     <p>{props.value ? props.value : "No value."}</p>
   </div>
 );

If you Babel-it it will create something like this:

 var ChildComponent = function ChildComponent(props) {
   return React.createElement(
     "div",
     null,
     React.createElement(
       "p",
       null,
       props.value ? props.value : "No value."
     )
   );
 };
Shutin answered 23/1, 2017 at 19:47 Comment(0)
G
0

For some reason, what seems to work for me is a variation on Shubham's answer above:

const ChildComponent = props => (
   <div>
      <h1>Child Component {props[0].someProp}</h1>
   </div>
)
Gley answered 16/6, 2017 at 19:5 Comment(0)
C
0

Using this

const ParentComponent = ({ prop1, prop2, prop3 }) => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent {...{ prop1, prop2, prop3 }} />
   </div>
);

const ChildComponent = ({ prop1, prop2, prop3 }) =>{
  <div>
    <h1>Child Component with prop1={prop1}</h1>
    <h1>Child Component with prop2={prop2}</h1>
    <h1>Child Component with prop2={prop3}</h1>
  </div>
}
Corabelle answered 9/5, 2018 at 10:19 Comment(1)
I am seeing "prop1, prop2, prop3" recur several times here. I think the idea is to have that effect without actually copying/pasting argument lists each time.Pneumothorax

© 2022 - 2024 — McMap. All rights reserved.