state
, you can also define methods for your component class. A class method typically needs to use the this
keyword so it can access properties on the class (such as state
and props
) inside the scope of the method. There are a few ways to allow your class methods to access this
.
One common way is to explicitly bind this
in the constructor so this
becomes bound to the class methods when the component is initialized. You may have noticed the last challenge used this.handleClick = this.handleClick.bind(this)
for its handleClick
method in the constructor. Then, when you call a function like this.setState()
within your class method, this
refers to the class and will not be undefined
.
Note: The this
keyword is one of the most confusing aspects of JavaScript but it plays an important role in React. Although its behavior here is totally normal, these lessons aren't the place for an in-depth review of this
so please refer to other lessons if the above is confusing!
state
that keeps track of an item count. It also has a method which allows you to increment this item count. However, the method doesn't work because it's using the this
keyword that is undefined. Fix it by explicitly binding this
to the addItem()
method in the component's constructor.
Next, add a click handler to the button
element in the render method. It should trigger the addItem()
method when the button receives a click event. Remember that the method you pass to the onClick
handler needs curly braces because it should be interpreted directly as JavaScript.
Once you complete the above steps you should be able to click the button and see the item count increment in the HTML.
MyComponent
should return a div
element which wraps two elements, a button and an h1
element, in that order.
testString: assert(Enzyme.mount(React.createElement(MyComponent)).find('div').length === 1 && Enzyme.mount(React.createElement(MyComponent)).find('div').childAt(0).type() === 'button' && Enzyme.mount(React.createElement(MyComponent)).find('div').childAt(1).type() === 'h1', 'MyComponent
should return a div
element which wraps two elements, a button and an h1
element, in that order.');
- text: 'The state of MyComponent
should initialize with the key value pair { itemCount: 0 }
.'
testString: 'assert(Enzyme.mount(React.createElement(MyComponent)).state(''itemCount'') === 0, ''The state of MyComponent
should initialize with the key value pair { itemCount: 0 }
.'');'
- text: Clicking the button
element should run the addItem
method and increment the state itemCount
by 1
.
testString: 'async () => { const waitForIt = (fn) => new Promise((resolve, reject) => setTimeout(() => resolve(fn()), 250)); const mockedComponent = Enzyme.mount(React.createElement(MyComponent)); const first = () => { mockedComponent.setState({ itemCount: 0 }); return waitForIt(() => mockedComponent.state(''itemCount'')); }; const second = () => { mockedComponent.find(''button'').simulate(''click''); return waitForIt(() => mockedComponent.state(''itemCount'')); }; const firstValue = await first(); const secondValue = await second(); assert(firstValue === 0 && secondValue === 1, ''Clicking the button
element should run the addItem
method and increment the state itemCount
by 1
.''); };'
```