Leon Gaban Leon Gaban - 2 years ago 152
React JSX Question

React/Jest error: services.map is not a function

enter image description here

I have a ServicesContainer that looks for the servicesReducer to render a list of ServiceCards.

ServicesContainer



import React, { Component } from 'react'
import { connect } from 'react-redux'
import { ServiceCard } from '../../components'

export class ServicesContainer extends Component {
constructor(props) {
super(props);
this.state = {
services: props.state.servicesReducer.services
}
}

onFormSubmit(e, user) {
e.preventDefault();
this.props.searchUser(user)
}

render() {
const services = this.state.services;

return (
<div className='services-container'>
<ul>
{ services.map(service =>
<ServiceCard
key={ service.name }
name={ service.name }
description={ service.description }
admins={ service.admins }
group={ service.group } />) }
</ul>
</div>
)
}
}

const mapStateToProps = (state) => {
return {
state
}
}

const ServicesListContainer = ServicesContainer;
export default connect(mapStateToProps, null)(ServicesListContainer)


ServicesContainer.test



Everything works fine here, but the test does not like the state I'm passing into it:

import React from 'react'
import * as enzyme from 'enzyme'
import toJson from 'enzyme-to-json'

import { ServicesContainer } from './ServicesContainer'
import ServiceCard from '../../components/Services/serviceCard'
import { initialServicesState } from '../../reducers/Services/servicesReducer'

const state = {
servicesReducer: {
services: initialServicesState
}
}

const servicesContainer = enzyme.shallow(<ServicesContainer state={ state }/>);

describe('<ServicesContainer /> component', () => {

it('should render', () => {
const tree = toJson(servicesContainer);
expect(tree).toMatchSnapshot();
});

});


^ the initialServicesState from the servicesReducer



export const initialServicesState = {
services: [
{
_id: _id,
name: "GeoStore",
description: "Manage store delivery zones",
admins: [ "Chuck Roe", "Steve Wonder" ],
group: "Black Flag"
},
{
_id: _id2,
name: "Rights Manager UI",
description: "Manage all internal applications and services",
admins: [ "Chuck Roe", "Steve Wonder" ],
group: "Black Flag"
}
]
}


ServiceCard component



import React, { Component } from 'react'

export default class ServiceCard extends React.Component {
constructor(props) {
super(props);
}

render () {
const name = this.props.name;
const description = this.props.description;
const admins = this.props.admins;
const group = this.props.group;

return (
<section className="service-card">
<h4>{ name }</h4>
<p>{ description }</p>
<em>{ group }</em>
<div className="services-admins">
<ul>
<li>
{ admins.map(admin => admin) }
</li>
</ul>
</div>
</section>
)
}
}


This is what the Redux State looks like in the ServicesContainer:

enter image description here

Answer Source

The issue is that you are building the props with the property "services" duplicated.

here are the relevant parts:

On the component you get state.serviceReducer.services from passed props

this.state = {
    services: props.state.servicesReducer.services
}

the props are passed here, and services gets the value from the import:

import { initialServicesState } from '../../reducers/Services/servicesReducer'

const state = {
   servicesReducer: {
       services: initialServicesState
    }
}

const servicesContainer = enzyme.shallow(<ServicesContainer state={ state }/>);

And the import comes from this export that is an object with a services property.

export const initialServicesState = {
    services: [
        {
           _id: _id,
           name: "GeoStore",

so, you have to either change the export to

export const initialServicesState = 
    [
        {
            _id: _id,
            name: "GeoStore",

or the props building to

const state = {
    servicesReducer: {
        services: initialServicesState.services
    }
}

as you had already figured in your answer.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download