Reputation: 73
I have a component that has an input and a button. When a user types a hobby in the input, it is suppose to send that string to be updated to an api. I have set up my test and I am testing whether or not the component exists and I am getting the error TypeError: Cannot read property 'map' of undefined, when I console.log(component). It says that the component is undefined.
When I comment out the {this.state.hobbies.map()} section (including the second render and everything inside of that), the component is able to render.
EditProfile.js
import React, { Component } from 'react';
import { MdDelete } from 'react-icons/md';
import { updateHobbies } from '../../services/updateHobbies';
import './edit_profile.scss';
import PropTypes from 'prop-types';
class EditProfile extends Component {
state = {
hobbies: this.props.employeeHobbies,
userInput: ''
};
handleChange = e => {
this.setState({ userInput: e.target.value });
};
handleButtonClick = () => {
const hobby = this.state.hobbies.concat(this.state.userInput);
this.setState({ hobbies: hobby, userInput: '' }, () =>
updateHobbies(this.state.hobbies));
};
handleDelete = e => {
const array = [...this.state.hobbies];
const index = array.indexOf(e);
if (index !== -1) {
array.splice(index, 1);
this.setState({ hobbies: array }, () =>
updateHobbies(this.state.hobbies));
}
};
render() {
return (
<div>
<label className='employee-label'>HOBBIES: </label>
<span>
<input type='text' value={this.state.userInput} onChange=
{this.handleChange} />
<button className='update-details-button' onClick=
{this.handleButtonClick}>
Add
</button>
{this.state.hobbies.map(hobbies => {
return (
<li className='employee-tag-list' key={hobbies}>
{hobbies}
<span className='delete-icons' onClick={() =>
this.handleDelete(hobbies)}>
<MdDelete />
</span>
</li>
);
})}
</span>
</div>
);
}
}
EditProfile.propTypes = {
employeeHobbies: PropTypes.array
};
export default EditProfile;
EditProfile.test.js
let component;
const chance = new Chance();
let mockHandleChange = jest.fn();
let mockHandleButtonClick = jest.fn();
let mockHandleDelete = jest.fn();
let mockUpdateHobbies;
let mockHobbies = [chance.string(), chance.string(), chance.string()];
function requiredProps(overrides = {}) {
return {
handleChange: mockHandleChange,
handleButtonClick: mockHandleButtonClick,
handleDelete: mockHandleDelete,
...overrides
};
}
function renderComponent(props = requiredProps()) {
return shallow(<Hobbies {...props} />);
}
beforeEach(() => {
component = renderComponent();
});
it('should exist', () => {
console.log(component.debug());
expect(component).toHaveLength(1);
});
I expected the test to pass but I am getting the error, TypeError: Cannot read property 'map' of undefined
Upvotes: 6
Views: 12843
Reputation: 38151
There are a few things that you can do, that all aim to solve the core problem: you are not supplying a value for the employeeHobbies
prop in your test.
Pick one of the following:
employeeHobbies
if it isn't supplied. EditProfile.defaultProps = { employeeHobbies: [] };
.requiredProps()
function in your test file, specify a value for employeeHobbies
of an empty array along with your other properties like handleChange
, handleButtonClick
, etc.state.employeeHobbies
, set it to this.props.employeeHobbies || [],
so it has a fallback value if passed null or nothing (undefined).I also recommend you specify the proptype for employeeHobbies
as PropTypes.array.isRequired
to get a helpful warning when the array isn't supplied. That will guard against misuse of the component, and violating the contract it needs to work.
Upvotes: 3