Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript React Basics (retired) Designing Data Flow Building the Statistics Component

Jeffrey James
Jeffrey James
2,636 Points

Relationship between onChange and onScoreChange

Trying to wrap my head around the following:

a) In the render function for the application class, within the map(..) call, each player's set of props includes a func called onScoreChange - fine

b) however, I'm not connecting the dots between this line

<btn className="counter-action decrement" onClick={function() {props.onChange(-1);}} > - </btn>

and how the (-1) or (1) are passed to the anon function below

onScoreChange={function(delta) {this.onScoreChange(id, delta)}.bind(this)}

It feels like this

function(delta) and props.onChange(x) are the same thing, but my brain isn't making the connection.

4 Answers

Dennis Brown
Dennis Brown
28,742 Points

Yes, that is correct.

The Application render function is rendering the Player Component, and sending the onScoreChange function "upstream" to the Player Component through props.onScoreChange. The Player component then renders the Counter component, and then passes the props.onScoreChange function on to the Counter as "props.onChange". Since it's already packaged up, and simply passing through Player, is why it can simply call with {props.onScoreChange}. That one function has gone "upstream" through 3 components, but still lives and executes in the originating component (Application).

Since Counter is a "stateless" component, it is what you can call a "dumb component". It doesn't do anything on it's own, without the help of another component. When you pass props to these dumb components (upstream, since they are laid on top of the main render function, and cannot send props back), we send it a static property, or a function to call in a local scope of another component. So we send it the index (Player), and delta (amount to change). We're passing it the onScoreChange method to use when the onClick event is executed. So even though it's called in the Counter component, the function itself is actually happening back in Application, which holds the scope of onScoreChange; Counter is simply calling it and giving it some parameters to work with.

It indeed follows a great pattern, and you will see anonymous functions all over with ES5. Everything in your component is a modular method, so you will have a object literal writing ( key: function(param) { ... } ). This can be a bit confusing, since it's just more repetitive code.

If you haven't taken the ES6 course yet, I would highly recommend it, and then look at the React docs to see the ES6 counter-parts. This will help make more sense of the component layout, lifecycle, and having the minimal amount of code being used. (e.g. React Components).

Just keep at it! React is not the easiest thing to understand at first. Since it's on the border of the functional programming paradigm, it's also not something that can be easily comprehended in a day. Just keep trying to learn a little more each time. :)

I hope that helps clarify something, and not cause more confusion. My apologies if it does. :S

Dennis Brown
Dennis Brown
28,742 Points

This is definitely something that will trip anyone up when getting started with React especially in ES5 (imo).

You probably understand this much, but just in case: When onScoreChange is called within the Counter component, it then becomes the parameter for the "onChange" property (props.onChange). When it's accessed, the onScoreChange function exists, but as "onChange", and since it was passed through props, it because props.onChange. We then add this to the mouse event, calling the onScoreChange function when called (on mouse click).

I believe the above is what can certainly throw you off when passing params to the function within props. We are still calling the same function, but under a different name, and in a module style. So, the delta is what you are passing to change the score, but the additional code needed to keep the lexical scope, and function causes extra confusion.

Just so you know, chances are you may not even see this ES5 style when working with React in the future, as ES6 saves so much time and space, and allows for better code, and pure functionality.

onScoreChange = (id, delta) => { .. }  // remove need for bind, and simply passing a function to 
<Counter onClick={onScoreChange(index, delta)} />

I hope that helps!

Jeffrey James
Jeffrey James
2,636 Points

Thanks Dennis Brown - so just repeating back what you said in a way my brain works (can you confirm the below is true?)

In the Counter "stateless functional component", we use an anonymous function to send data "up stream", by way of attaching it to a prop. In this case, "up stream" means to the instantiation of the Counter within the functional stateless Player component (though the player is not really created yet).

When the Player component is actually "realized" in the Application class which is managing "application state" (the upper limit of our up stream so far), we provide a definition for onScoreChange which does the following:

  • uses the value passed into the anon function from Counter, which is a "dumb" way to know whether to increase or decrease score
  • takes that up/down vote and determines how to apply it to each Player, with the simple array indexing between the map arg that tracks position in the call and the position of the player in the state object.

if this is correct, I either feel very dumb, or perhaps this is a recurring pattern that's used over and over again? Anon functions all over the place in children and voodoo around them as you get closer to the state mgmt class?

Thanks much.

Jeff

Jeffrey James
Jeffrey James
2,636 Points

Thanks Dennis - agreed, gotta at least put in 20-30 hours before anything really gets internalized, just wanted to make sure I was on the right track. Appreciate the thorough responses. The end of this class was more intuitive and now I'm on to the webpack config for react, then I'll check the ES2015 course.

Jeff

Dennis Brown
Dennis Brown
28,742 Points

You are very welcome! I'm just glad to see it makes more sense now, because I remember going through the same woes.

When you get ready to setup your own environment, you can always make it easy on yourself, and grab a React Boilerplate. Dan Abramov (Facebook/React), recently created a new hot-reloading boilerplate that's quite nice for newer React users. :)

Happy Reacting!

Jeffrey James
Jeffrey James
2,636 Points

Ha, already battling configuration issues :). Will try the boilerplate.