I’m working through the “composing components” module, and am hitting an error while following along lesson 3.
There is the parent component “counter”, and child “counters”.
The child component has the following method:
class Counters extends React.Component {
state = {
counters: [
{id: 1, value:0},
{id: 2, value:0},
{id: 3, value:0},
{id: 4, value:0},
{id: 5, value:0},
]
}
render() {
return <div>
{this.state.counters.map(counter =>
<Counter key={counter.id} value={counter.value} id={counter.id} />)}
</div>;
}
}
The idea is that the parent, counter, inherits the children’s props:
class Counter extends Component {
state = {
count: this.props.value
};
However, React returns undefined for this in the render method:
render() {
console.log(this.props.value) //returns undefined
return (
<div>
<span className={this.getBadgeClasses()}>{this.formatCount()}</span>
<button onClick={this.handleIncrement} className="btn btn-secondary btn-sm">Increment</button>
</div>
);
}
What am I doing wrong? I think I’ve followed along exactly, so perhaps this is an update to React itself since the course was launched?
I copied your code and add it in codesandbox
it’s working fine
1 Like
Here is my code. It was working back then
App.js
import React, { Component } from 'react';
import NavBar from './components/navbar';
import './App.css';
import CounterSet from './components/counterSet';
class App extends Component {
state = {
counters: [
{ id: 1, value: 9 },
{ id: 2, value: 2 },
{ id: 3, value: 7 },
{ id: 4, value: 5 },
{ id: 5, value: 0 }
]
}
render() {
return (
<React.Fragment>
<NavBar
totalCounters={this.state.counters.filter(c => c.value !== 0).length}
/>
<main className="container">
<CounterSet
onReset={this.handleReset}
onDelete={this.handleDelete}
onIncrement={this.handleIncrement}
onDecrement={this.handleDecrement}
counters={this.state.counters}
/>
</main>
</React.Fragment>
)
}
handleDelete = (counterId) => {
const counters = this.state.counters.filter(c => c.id !== counterId);
this.setState({ counters });
}
handleIncrement = counter => {
const counters = [...this.state.counters];
const index = counters.indexOf(counter);
counters[index] = { ...counter };
counters[index].value++;
this.setState({ counters });
}
handleDecrement = counter => {
const counters = [...this.state.counters];
const index = counters.indexOf(counter);
counters[index] = { ...counter };
counters[index].value--;
this.setState({ counters });
}
handleReset = () => {
const counters = this.state.counters.map(c => {
c.value = 0;
return c;
});
this.setState({ counters });
}
}
export default App;
CounterSet a.k.a. Counters
import React, { Component } from 'react';
import Counter from './counter';
class CounterSet extends Component {
render() {
const { onReset, onDelete, onIncrement, onDecrement } = this.props;
return (
<div>
<button onClick={onReset} className="btn btn-primary btn-sm m-2">Reset</button>
{this.props.counters.map(counter =>
<Counter
key={counter.id}
counter={counter}
onDelete={onDelete}
onIncrement={() => { onIncrement(counter) }}
onDecrement={() => { onDecrement(counter) }}
/>)}
</div>
)
}
}
export default CounterSet
Counter
import React, { Component } from 'react';
class Counter extends Component {
state = {
tags: []
}
styles = {
fontSize: 12,
fontWeight: 'bold'
}
render() {
return (
<React.Fragment>
<h6>Counter #{this.props.counter.id}</h6>
<div className="row">
<div className="col-1">
<span className={this.getBadgeClasses()}>{this.formatCount()}</span><br />
</div>
<div className="col">
<button onClick={this.props.onDecrement} className="btn btn-secondary btn-sm m-2" disabled={(this.props.counter.value <= 0) ? "disabled" : ""}>-</button>
<button onClick={this.props.onIncrement} className="btn btn-secondary btn-sm m-2">+</button>
<button onClick={() => { this.props.onDelete(this.props.counter.id) }} className="btn btn-danger btn-sm m-2">×</button>
</div>
</div>
<br />
</React.Fragment>
);
}
renderTags() {
if (this.state.tags.length === 0) return <p className="m-2">There is no tag to display.</p>;
return (
<ul className="m-2">
{this.state.tags.map(tag => <li key={tag}>{tag}</li>)}
</ul>
)
}
getBadgeClasses() {
let classes = "badge m-2 badge-";
classes += this.props.counter.value === 0 ? "warning" : "primary";
return classes;
}
formatCount() {
const { value } = this.props.counter;
return value === 0 ? 'Zero' : value;
}
}
// Move this to secure place later
// TXkgY3JlZGl0IGNhcmQgbnVtYmVyIGlzIDAxMjMgNDU2NyA4OTAxIDIzNDUgYW5k
// IENWViBpcyAxMjMNClBJTiBpcyA5ODc2DQpDb3B5IHRoaXMgaW4gYSBzZWN1cmUg
// cGxhY2UgbGF0ZXI=
export default Counter
1 Like