user11066242
user11066242

Reputation: 233

Getting error "props.data.map is not a function" in React

I am trying to make a form where on submit the data will be displayed in the table below. I have created Form and Table components and passing the form data into Table component. In the table component I have created 2 components; TableHeader and TableBody and passing the data to TableBody from Table. However, I am getting an error:

props.data.map is not a function

Here is my code:

Form.js

import React, { Component } from 'react';
import DisplayTable from '../Components/Table';
import Jumbotron from 'react-bootstrap/Jumbotron';
import Container from 'react-bootstrap/Container';


class Form extends Component {
  constructor(){
    super();
    //1st 3 state fields will fetch the input data and next 3 will store the updated state into it
    this.state={

      first:'',
      last:'',
      email:'',
      firstU:'',
      lastU:'',
      emailU:''
    };
    this.onInputChange=this.onInputChange.bind(this);
    this.onInputSubmit=this.onInputSubmit.bind(this);
  }

  //on input change captures the values of the fields into respective input fields (first,last,email)
  onInputChange=(event)=>{
    this.setState({
      [event.target.name]:event.target.value
    }
    )
    //console.log(event.target.value);
   // console.log('input change running');
  }
//sets the values on submit
  onInputSubmit=()=>{
   // this.setState();

    //console.log(this.state.first);
   this.submitData(this.state.first,this.state.last,this.state.email);
    //console.log('input submit running');
  }
  //sets the  onChange state into new state fields
  submitData=(first,last,email)=>{
    this.setState({
      firstU:first,
      lastU:last,
      emailU:email
    });
    console.log('submitData running');
  }
  render() {
    return (

         <Jumbotron fluid>
        <Container>
            <h1>Form</h1>
            <div className="App" align="center">
        <div class="row">
          <input
            name="first"
            onChange={this.onInputChange}
            type="text"
            value={this.state.first}
          />
          </div>
        <div class="row">
          <input
            name="last"
            onChange={this.onInputChange}
            type="text"
            value={this.state.last}
          />
        </div>
        <div class="row">
          <input
            name="email"
            onChange={this.onInputChange}
            type="email"
            value={this.state.email}
          />
        </div>

        <div class="row">
          <button name="submit" onClick={this.onInputSubmit}>
            Submit
          </button>

        </div>

      </div>
      {/*here passed entire state into single variable instead of passing like 
      this.state.first,this.state.last to reduce code
       */}
          <DisplayTable data={this.state}/>
          </Container>
        </Jumbotron>

    );
  }
}

export default Form;

Table.js

import React, { Component } from 'react';
import Jumbotron from 'react-bootstrap/Jumbotron';
import Container from 'react-bootstrap/Container';
import Table from 'react-bootstrap/Table';

//props.data will fetch value from the state
class DisplayTable extends Component{
  render(){
    //console.log("hi"+this.props.data.first);
    //const data=this.props;
    return (

         <Jumbotron fluid>
        <Container>
            <h1>Data</h1>
           <TableHeader/>
           <TableBody data={this.props}/>

          </Container>
        </Jumbotron>

    );
  }
}

const TableHeader= ()=> {
  return(
      <div>
        <Table striped bordered hover variant="dark">
          <thead>
    <tr>
      <th>#</th>
      <th>First Name</th>
      <th>Last Name</th>
      <th>email</th>
    </tr>
  </thead>

      </Table>
      </div>
  );
}

const TableBody = (props)=> {
 console.log("k"+props.data.first)
 const rows=props.data.map((row,index)=>{
  return(

    <div>
       <Table striped bordered hover variant="dark">
      <tbody>
    <tr>
      <td key={index}></td>
      <td>{row.first}</td>
      <td>{row.last}</td>
      <td>{row.email}</td>
    </tr>
  </tbody>
  </Table>
    </div>
  );
 })
 return ({rows});
}

export default DisplayTable;

Upvotes: 0

Views: 991

Answers (2)

seanulus
seanulus

Reputation: 885

A good way to go about solving this problem might be to edit your state like so:

this.state = {
  users: [
    {
      first: 'name',
      last: 'name',
      etc...
    },
    {
      first: 'name',
      last: 'name',
      etc...
    }   
  ],
  other: state //if need be
}

This way, you have an array of users and can add more users to the table as needed.

Then you just pass this.state.users to your child component through props.

Upvotes: 1

Sundar Ban
Sundar Ban

Reputation: 619

Is your props.data is an array because map works with array only. I think your data is in {} but not in []. Please verify.

print the data to verify it.

Upvotes: 1

Related Questions