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 trialMatthew Anderson
322 PointsTypeError: Cannot read property 'props' of undefined
Here is my workspace: https://w.trhou.se/7wkhddyoo8 (modified the link, thank you @Steven Parker)
More specifically, here is the offending code:
const Counter = React.createClass({
propTypes: {
score: React.PropTypes.number.isRequired,
},
render: () => {
return (
<div className="counter">
<button className="counter-action decrement"> - </button>
<div className="counter-score"> {this.props.score} </div>
<button className="counter-action increment"> + </button>
</div>
);
}
});
According to the compiler, props does not exist. However, through the Player SFC, I am passing in the score property to the Counter component:
const Player = (props) => {
return(
<div className="player">
<div className="player-name">
{props.name}
</div>
<div className="player-score">
<Counter score={props.score}/>
</div>
</div>
);
};
Thank you!
Edit Console Error:
Uncaught TypeError: Cannot read property 'props' of undefined
at Constructor.render (eval at transform.run (babel-browser.min.js:4), <anonymous>:53:19)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (react.js:6157)
at ReactCompositeComponentWrapper._renderValidatedComponent (react.js:6177)
at ReactCompositeComponentWrapper.wrapper [as _renderValidatedComponent] (react.js:12513)
at ReactCompositeComponentWrapper.performInitialMount (react.js:5761)
at ReactCompositeComponentWrapper.mountComponent (react.js:5692)
at ReactCompositeComponentWrapper.wrapper [as mountComponent] (react.js:12513)
at Object.mountComponent (react.js:13175)
at ReactDOMComponent.mountChildren (react.js:11891)
at ReactDOMComponent._createInitialChildren (react.js:7055)
/favicon.ico Failed to load resource: the server responded with a status of 404 (Not Found)
Zack Lee
Courses Plus Student 17,662 Pointsthe workspace link is not working. can you post the code of all your modules? also you can format your code so its more readable by surrounding it with 3 ticks (```) like so:
```javascript
...code goes here
```
Matthew Anderson
322 PointsThank you, I wasn't aware I could post markdown here (read, Matt... READ). Also, the link has been modified (https://w.trhou.se/7wkhddyoo8).
Sam Gord
14,084 Pointsfound the solution for this, at THIS STAGE of the course . probably things are going to change later ( or already has changed ) but, to fix this at this stage you DON'T have to use ARROW function, write it like this and it works -->
const Counter = React.createClass({
propTypes: {
score: React.PropTypes.number.isRequired,
},
render: function() {
return (
<div className="counter">
<button className="counter-action decrement"> - </button>
<div className="counter-score"> {this.props.score} </div>
<button className="counter-action increment"> + </button>
</div>
);
}
});
5 Answers
Zack Lee
Courses Plus Student 17,662 PointsI think you're getting some sort of binding issue with the "this" keyword in your counter. I'm referencing the workspace I have for this course, but the code is much different because I finished the course.
Try just using "props.score" instead of "this.props.score"
Matthew Anderson
322 PointsUnfortunately, this does not fix the issue. Since Counter
is a Class Component, I need the this
keyword to handle the current state.
Zack Lee
Courses Plus Student 17,662 Pointscan you share your console error?
Matthew Anderson
322 PointsUncaught TypeError: Cannot read property 'props' of undefined
at Constructor.render (eval at transform.run (babel-browser.min.js:4), <anonymous>:53:19)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (react.js:6157)
at ReactCompositeComponentWrapper._renderValidatedComponent (react.js:6177)
at ReactCompositeComponentWrapper.wrapper [as _renderValidatedComponent] (react.js:12513)
at ReactCompositeComponentWrapper.performInitialMount (react.js:5761)
at ReactCompositeComponentWrapper.mountComponent (react.js:5692)
at ReactCompositeComponentWrapper.wrapper [as mountComponent] (react.js:12513)
at Object.mountComponent (react.js:13175)
at ReactDOMComponent.mountChildren (react.js:11891)
at ReactDOMComponent._createInitialChildren (react.js:7055)
/favicon.ico Failed to load resource: the server responded with a status of 404 (Not Found)
Zack Lee
Courses Plus Student 17,662 PointsI would maybe look into updating the syntax for the counter class. I would change it from a class to a function, for me this is just more explicit with the intentions of the component. it would look similar to the syntax of your player component and allows you to pass the props component explicitly.
const Counter = (props) => {
return (
<div className="counter">
<button className="counter-action decrement"> - </button>
<div className="counter-score"> {this.score} </div>
<button className="counter-action increment"> + </button>
</div>
);
};
Counter.propTypes = {
score: React.PropTypes.number.isRequired,
}
Matthew Anderson
322 PointsHonestly, this doesn't seem like a good solution to me. The Counter component is Class-based for a reason (as far as I can tell), as it must have the ability to modify its own state. Thank you for the help, but I fear this is treating the symptom rather than the disease.
Matthew Anderson
322 PointsI opted to use class Counter extends React.Component
instead of const Counter = React.createClass()
. This fixed the problem with this
not being defined.
const PLAYERS = [
{
name: "Matt Anderson",
score: 19,
id: 1
},
{
name: "Josh Waitzkin",
score: 420,
id: 2,
},
{
name: "Ray Bradburry",
score: 666,
id: 3,
}
];
const Header = (props) => {
return(
<div className="header">
<h1>{props.title}</h1>
</div>
);
}
Header.propTypes = {
title: React.PropTypes.string.isRequired,
};
//const Counter = React.createClass({
// propTypes: {
// score: React.PropTypes.number.isRequired,
// },
// render: () => {
// return (
// <div className="counter">
// <button className="counter-action decrement"> - </button>
// <div className="counter-score"> {this.props.score} </div>
// <button className="counter-action increment"> + </button>
// </div>
// );
// }
//});
class Counter extends React.Component {
constructor(props) {
super(props);
}
render() {
return(
<div className="counter">
<button className="counter-action decrement"> - </button>
<div className="counter-score"> {this.props.score} </div>
<button className="counter-action increment"> + </button>
</div>
);
}
}
Counter.propTypes = {
score: React.PropTypes.number.isRequired,
};
const Player = (props) => {
return(
<div className="player">
<div className="player-name">
{props.name}
</div>
<div className="player-score">
<Counter score={props.score}/>
</div>
</div>
);
};
Player.propTypes = {
name: React.PropTypes.string.isRequired,
score: React.PropTypes.number.isRequired,
}
function Application(props) {
return (
<div className="scoreboard">
<Header title={props.title}/>
<div className="players">
{props.players.map((player) => {
return <Player name={player.name} score={player.score} key={player.id}/>
})}
</div>
</div>
);
}
Application.defaultProps = {
title: "Scoreboard",
players: React.PropTypes.arrayOf(React.PropTypes.shape({
name: React.PropTypes.string.isRequired,
score: React.PropTypes.number.isRequired,
id: React.PropTypes.number.isRequired,
})).isRequired,
};
ReactDOM.render(<Application players={PLAYERS}/>, document.getElementById('container'));
Zack Lee
Courses Plus Student 17,662 Pointslater in the course you'll end up turning counter into a function because you actually don't want it to have its own state. You end up pushing the state to the top level component so that all your state is in one place so its more easily accessible by other components, which is usually best practice. this become clearer when you start keeping track of all player scores in another component to display a leaderboard of sorts. having the state is the top component makes it easy to access. As they say, "a single source of truth."
You will however create a stop watch component that will be a component extended class because the state is not needed elsewhere in the application, so it is left to be its own stateful component.
Liam Lagan
10,517 PointsI had a similar error due to mistakenly adding "this" to the wrong function by mistake.
Ari Misha
19,323 PointsHiya there! You're receiving the error coz props arent defined. Your Player component needs a props checking or propTypes validation. The name and score needs a validation for propTypes. Do that and you're good to go. (:
~ Ari
Steven Parker
231,268 PointsSteven Parker
231,268 PointsYou can't share a direct URL to your workspace, it's temporary and only exists while you are using it.
But you can use the snapshot function in the workspace and provide the link to that.