FAQ: this.props - this.props Recap

This community-built FAQ covers the “this.props Recap” exercise from the lesson “this.props”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Web Development

Learn ReactJS: Part I

FAQs on the exercise this.props Recap

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

2 Likes

Hi!! I was a bit confused about how better to pass the argument to the event handler function, solved wrapping it in an arrow function:

3 Likes

Hi! I’m a bit confused why your code work and mine doesn’t. We did almost the same thing, but a added the handleClick in App.js instead GroceryItem.js, then used onClick={handleClick} at each

The click works fine, but at the alert message, the ${item} doesn’t show up, and the message that pops up is “[object Object] has been added to the cart.”

Here is my code for App.js:

import React from 'react';
import GroceryItem from './GroceryItem';

function App() {
  function handleClick(item) {
    alert(`${item} has been added to the cart.`);
  }
  return (
    <div>
      <GroceryItem item="Eggs" onClick={handleClick}/>
      <GroceryItem item="Banana" onClick={handleClick}/>
      <GroceryItem item="Strawberry" onClick={handleClick}/>
      <GroceryItem item="Bread" onClick={handleClick}/>
    </div>
  );
}

export default App

Here is my code for GroceryItem.js

import React from 'react';

function GroceryItem(props) {
  return (
    <button onClick={props.onClick}>{props.item}</button>
  );
}

export default GroceryItem;

For your proposed alternative solution, you could try the following.

In GroceryItem.js,

// You wrote:
<button onClick={props.onClick}>{props.item}</button>

// Try changing it to:
<button onClick={()=>props.onClick(props.item)}>{props.item}</button>

As for the '[object Object] has been added to the cart.' message, that object is most likely the SyntheticEvent:

If you want to look at that object, you can try the following:

<button onClick={(e)=>{console.log(e); props.onClick(props.item)}}>{props.item}</button>

The object will show up in your brower’s console. The alert will still show props.item.

Actually, just using a function inside onClick of GroceryItem, worked and logged the correct message with the clicked item being displayed. I think I understood… I need to pass this function inside the onClick to pass the props.item to the event handler, so it can alert with the correct ${item}, right?

Thanks for your help!!

1 Like

Hey! I really did struggle with this but after watching a few extra videos on YouTube, I have finally come to this solution and understanding. I hope this explanation helps those who it needs to help.
Within App.js:

import React from 'react';
import GroceryItem from './GroceryItem';

function App() {
  
  return (
    <div>
      <GroceryItem item="Eggs" />
      <GroceryItem item="Banana" />
      <GroceryItem item="Strawberry" />
      <GroceryItem item="Bread" />
    </div>
  );
}

export default App

Within GroceryItems.js:

import React from 'react';

function GroceryItem({item}) {
  function handleClick() {
    alert(`${item} added to the cart!`);
  }
  return (
    <button onClick={handleClick}>
      {item}
    </button>
  );
};

// Can also be written as follows:

// function GroceryItem(props) {
//   function handleClick() {
//     alert(`${props.item} added to the cart!`);
//   }
//   return (
//     <button onClick={handleClick}>
//       {props.item}
//     </button>
//   );
// };

// OR! If you'd like to read my conclusion to follow, here is - in my opinion, 
// a more readable and self-explanatory solution for people of all levels to 
// understand... And it looks as follows:

// function GroceryItem(GroceryProps) {
//   function handleClick() {
//     alert(`${GroceryProps.item} added to the cart!`);
//   }
//   return (
//     <button onClick={handleClick}>
//       {GroceryProps.item}
//     </button>
//   );
// };

export default GroceryItem;

After looking at the solutions for App.js and GroceryItem.js above, and comparing them… What I have come to realise and learn about props being passed down through the React tree (zoomed in to see its components in detail) is that they can be visualised as follows… Let us take the first GroceryItem (Eggs) as an example in this visualisation:

//<GroceryItem item="Eggs">
//     imagine trying to access the Eggs value if GroceryItem was a JS object... 
//     Rhetorically, how might you do that?... Well, you'd type something like... 
//     'GroceryItem.item' to get the value of Eggs... 
//     Now imagine assigning this metaphorical GroceryItem object to the name of 
//     another newly declared variable, namely: 'props'... 
//     or even clearer, something like: 'GroceryProps'...
//     This same concept of the scope/access you have to certain values in a 
//     JS object can be applied to the scope/access a child component has to 
//     its parent component...
//<GroceryItem />

//               Applying this to an image would look like this:
//
//                                **GroceryItem**                                          
//                          + GroceryProps={"item"="Eggs"}                                         
//                                       | 
//                                       |    
//                                       V                       
//                                   **button**                              
//                        + GroceryProps.item  or  {item}   
//                    + ButtonProps={"onClick"="handleClick"}
//

The reason I feel this visualisation is so important to me is because I was struggling to understand that the ‘GroceryProps.item’ value was not automatically applied to the ButtonProps object… Mainly because in the exercise they refer to both the parent (GroceryItem, in this case, Eggs) and child (Button) components’ objects with the same name: ‘props’… But as a beginner, it is easier to see what is actually happening when you assign them different names specific to each component. i.e. GroceryProps & ButtonProps, to see and remind yourself that they are actually 2 completely different objects.

So while naming them the same thing (‘props’) is most likely what all advanced React developers end up doing for all their components… it is a terrible way to teach the underlying process of what is actually taking place to a beginner. @codecademy

5 Likes

I 100% agree Dylan.
Thank you for pointing that out!

1 Like

Based on the previous exercises in this lesson (with Talker.js and Button.js, the Button function is the one that accepts props; the Talker function returns an instance of ; and it is also the Talker function which contains the event handler function handleClick) I thought that the handleClick with the alert should go within App(), and not GroceryItem().
I found the Codecademy a little buggy so had to make a local version with create-react-app to test this out. I was also struggling to get the alert to include the item that had been clicked on, but after reading through these comments I implemented an arrow function and also added an argument to the handleClick, both of which worked, so thanks to @muhamed.berdimuradov and @dylandupont !
Anyway, here is my code. As mentioned, my handleClick is in a different place to the other examples. If anyone knows whether one or the other is the more “correct” solution, or if both methods are valid, I’d love to know! Thanks!

App.js:

import React from "react";
import "./App.css";
import GroceryItem from "./GroceryItem";

function App() {
  function handleClick(item) {
    alert(`${item} was added to cart!`);
  }
  return (
    <div>
      <GroceryItem
        name="Bread"
        price="£0.50"
        onClick={() => {
          handleClick("Bread");
        }}
      />
      <GroceryItem
        name="Cheese"
        price="£2.00"
        onClick={() => {
          handleClick("Cheese");
        }}
      />
    </div>
  );
}

export default App;

GroceryItem.js:

import React from "react";

function GroceryItem(props) {
  return (
    <button onClick={props.onClick}>
      {props.name} <br /> {props.price}
    </button>
  );
}

export default GroceryItem;

Hi Dylan,

I modify my code as your but I still dont get any alert message…

App
GroceryItem

Any idea?

Thanks

You wrote <div/> instead of </div>

Ohhh. I see !!! :smiley:

Fixed and done. Thank you very much

Hello, I have made my list diferentes, using an array inside of a property… It seems to work but im not sure if this is the right way to do??? Can you tell me??

my App.js:

import React from 'react';
import GroceryItem from './GroceryItem';

function App() {
  return <GroceryItem name={['breadaa', 'banana', 'strawberry', 'eggs']}    />
}


export default App

my GroceryItem.js:

import React from 'react';

function GroceryItem(props) {
  function handleClick() {
    alert('clicked');
  };
  /*let index = for( item in props.name) {
    index = prop.name[item];
  };*/
return (
  <div>
<h1>hello</h1>
<button onClick={handleClick}>{props.name[0]}</button>
<button >{props.name[1]}</button>
<button >{props.name[2]}</button>
<button >{props.name[3]}</button>

</div>
);
};

export default GroceryItem;

Also in my button I have to put the index of an array to each props.name property manually. Is there a way that js my buttons just autamically take the index of an array element?? I guess I can make it with a for loop but im not sure how to do it exactly…

If you don’t want to assign the array directly to the name property, then in App.js, perhaps you could do something like:

function App() {

  const groceries = ['breadaa', 'banana', 'strawberry', 'eggs'];

  return <GroceryItem name={groceries} />
}

And in GroceryItem.js, you could use of the map method (Array.prototype.map() - JavaScript | MDN) on the array:

return (
  <div>
    <h1>hello</h1>
    {props.name.map((grocery) => 
      <button key={grocery} onClick={handleClick}>{grocery}</button>)}
  </div>
);

The map method will return a new array whose elements will be the buttons.

If for some reason, you also want the index of the elements in the array, then the map method can be given a second optional parameter as well (see documentation). Suppose you wanted to give each button an id of 'button0', 'button1' and so on. Then you could do something like:

return (
    <div>
        <h1>hello</h1>
        {props.name.map((grocery, index) => 
           <button key={grocery} id={'button' + index} onClick={handleClick}>
           {grocery}
          </button>)}
    </div>
);

and then if so inclined, you could modify your handleClick function as:

function handleClick(e) {
    alert(e.target.id + ' clicked');
}
2 Likes

Hi Guys!

I’m not sure what I am doing wrong here, but my buttons do not seem to be rendering… Please see below my code:

import React from 'react'; import GroceryItem from './GroceryItem'; function App() { return ( <> <GroceryItem name="Eggs" /> <GroceryItem name="Banana" /> <GroceryItem name="Strawberry"/> <GroceryItem name="Bread"/> </> ) } export default App;
import React from 'react'; function GroceryItem(props) { function handleClick() { alert({props.name} + " has been added to the basket.") } return <button onClick={handleClick}>{props.name}</button> }; export default GroceryItem;

Any help is much appreciated!

// You wrote:
alert({props.name} + " has been added to the basket.")

// Try changing to:
alert(props.name + " has been added to the basket.")
1 Like

Many thanks! It worked. I got confused as to when I should be using curly braces to inject the javascript.

1 Like

My GroceryItem.js file:

import React from 'react';

function GroceryItem(props) {
  function handleClick() {
    if (props.name.charAt(props.name.length - 1) === 's') {
      alert(`${props.name} have been added to the cart`);
    } else {
      alert(`${props.name} has been added to the cart`);
    }
  }
  return <button onClick={handleClick}>{props.name}</button>;
}

export default GroceryItem;

My App.js file:

import React from 'react';
import GroceryItem from './GroceryItem.js';

function App() {
  return (
    <div>
      <GroceryItem name='Eggs' />
      <GroceryItem name='Banana' />
      <GroceryItem name='Strawberry' />
      <GroceryItem name='Oranges' />
    </div>
  );
}

export default App

My solution (initially looked harder than it was):

import './App.css'; import GroceryItem from './GroceryItem'; function App() { return ( <div className="App"> <header className="App-header"> <GroceryItem name="Eggs"/> <GroceryItem name="Banana"/> <GroceryItem name="Strawberry"/> <GroceryItem name="Bread"/> </header> </div> ); } export default App;
import React from 'react'; function GroceryItem(props) { const handleClick = () => { alert(props.name + " was added to the Shopping List") } return ( <div> <button onClick={handleClick}>{props.name}</button> </div> ) } export default GroceryItem;

I tried hard to be able to pass an array of grocery items to the component, but with no success… :frowning:

What I have been able to decipher is that, a lot of the time, following the examples from the lessons do NOT help!
If I had not come on this forum, I wouldn’t have ever found the solution!