简体   繁体   中英

Passing react-table row data to react-modal

Being new to React, I'm having a hard time to pass data from react-table to an "edit" modal and can't seem to find a solution for a similar problem. Data are fetched from the database by an Axios API call and rendered in a react-table. I need to pass data of a rendered row to a modal, in order to then make a put request and update the data to the server. The edit button is in the modal class and then rendered on the table.

Below you can see the modal&form class, which is then called in the table class.

import React, { Component, Fragment } from 'react';
import { Button, Modal, ModalHeader, ModalBody, Form, FormGroup, Input, Label } from 'reactstrap';
import Axios from 'axios';


class CompanyModal extends Component {
    constructor(props) {
        super(props);
    this.state = {
        modal: props.initialModalState,
        id: '',
        title: '',
        address: '',
        phoneNumber : '',
        email: ''
    };
    this.toggle = this.toggle.bind(this);
}

componentDidMount() {
    if (this.props.company) {
        const { id, title, address, phoneNumber, email } = this.props.company
        this.setState({ id,title, address, phoneNumber, email});
    }
}
onChange = e => {
    this.setState({ [e.target.name]: e.target.value })
}


submitNew = e => {
    e.preventDefault()
    Axios.post('localhost:44394/api/companies/Create', this.state)
    .then(res => {
    console.log(res)})
    .catch(error => {
        console.log(error)
    })
}

submitEdit = e =>{
    e.preventDefault()
    Axios.put(`localhost:44394/api/companies/update/${this.state.id}`, this.state)
    .then(res => {
        console.log(res)
    })
    .catch(error => {
        console.log(error)
    })
}
    toggle () {
        this.setState({
            modal: !this.state.modal
        });
    }

    render() {
        const isNew = this.props.isNew;

        let title = 'Edit Company';
        let button = '';
        if (isNew) {
            title = 'Add Company';

            button = <Button
                color="success"
                onClick={this.toggle}
                style={{ minWidth: "200px" }}>Add Company</Button>;
        } else {
            button = <Button
                className="btn-icon btn-round"
                size="sm"
                color="warning"
                onClick={this.toggle}><i className="fa fa-edit" />
                </Button>;
        }

        return <Fragment>
            {button}
            <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
                <ModalHeader toggle={this.toggle}>{title}</ModalHeader>
                <ModalBody>
                    <Form onSubmit={this.props.company ? this.submitEdit : this.submitNew}>
                        <FormGroup>
                            <Label for="name">Name:</Label>
                            <Input type="text" name="title" onChange={this.onChange} value= 
                                 {this.state.Title === '' ? '' : this.state.Title} />
                        </FormGroup>
                        <FormGroup>
                            <Label for="address">Address:</Label>
                            <Input type="text" name="address" onChange={this.onChange} value= 
                                 {this.state.address === null ? '' : this.state.company} />
                        </FormGroup>
                        <FormGroup>
                            <Label for="phoneNumber">Phone Number:</Label>
                            <Input type="number" name="phoneNumber" onChange={this.onChange} value= 
                                 {this.state.phoneNumber === null ? '' : this.state.phoneNumber} />
                        </FormGroup>
                        <FormGroup>
                            <Label for="email">Email:</Label>
                            <Input type="email" name="email" onChange={this.onChange} value= 
                                 {this.state.email === null ? '' : this.state.email} />
                        </FormGroup>
                        <Button type="submit">Submit</Button>
                    </Form>
                </ModalBody>
            </Modal>
        </Fragment>;
    }
    }
export default CompanyModal;

Table code


import React, { Component } from "react";
import ReactTable from "react-table";
import CompanyModal from "../Forms/CompanyModal";
import axios from "axios";
import {
  Card,
  CardBody,
  CardHeader,
  CardTitle,
  Row,
  Col,
  Button,
  ButtonToolBar
} from "reactstrap";

 var data

class CompanyTable extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      posts:[]
    };
  }


componentDidMount(){
  axios.get(`https://localhost:44394/api/companies`)
  .then(res => {
    const posts = res.data;
    this.setState({posts});
  })
}

  render() {
    const posts = this.props.posts;
    const columns =[
      {
        Header: "Id",
        accessor: "id",
        show: false
      },
      {
        Header: "Name",
        accessor: "title"
      },
      {
        Header: "Address",
        accessor: "adress"
      },
      {
        Header: "Phone Number",
        accessor: "phoneNumber"
      },
      {
        Header: "Actions",
        Cell: props =>{
          return ( 
            <div className="actions-right">




            <CompanyModal/>





            <div/>
          )
        },
        sortable: false,
        filterable: false
       }
    ]
    return (
      <>      
          <Row>
            <Col xs={12} md={12}>
              <Card>
                <CardHeader>
                  <CardTitle tag="h4">Companies</CardTitle>
                  <CompanyModal isNew/>
                </CardHeader>
                <CardBody>
                  <ReactTable
                    data={this.state.posts}
                    filterable
                    columns = {columns}
                    defaultPageSize={10}
                    showPaginationTop
                    showPaginationBottom={false}
                    className="-striped -highlight"
                    />                 
                </CardBody>
              </Card>
            </Col>
          </Row>          
      </>
    );
  }
}

export default CompanyTable;

You can use componentDidUpdate for the modal component to watch the props change and set the state.

( componentWillReceiveProps is now deprecated)

Suppose you want to pass prop exampleProp from the table view to the modal view:

class CompanyModal extends Component {
    constructor(props) {
        super(props);
    this.state = {
        exampleState: 'something'
        // ... other states
    };
}

... other code

componentDidUpdate(nextProps) {

 if (nextProps.exampleProp !== this.props.exampleProp) {// New prop value
this.setState({exampleState: nextProps.exampleProp})
}
}

... other code

In your table view:


        Header: "Actions",
        Cell: props =>{
          return ( 
            <div className="actions-right">
            <CompanyModal exampleProp={this.state.yourTableViewState} />
            <div/>
          )
        },
        sortable: false,
        filterable: false
       }

I solved this using hooks by doing this:

const [show, setShow] = useState(false);
const [selectedRow, setSelectedRow] = useState({});

const handleClose = () => setShow(false);
const handleShow = (selected) => {
  setSelectedRow(selected);
  setShow(true);
  };

I created a useState var to contain which row had been clicked; then use the setter to update the state var.

The only thing that was tricky was getting the original row data from react-table, but it ended up being very simple.

In the component (or where ever you want to trigger the modal show), add an onClick prop and pass the your handleShow the row.original to get all the data.

<tbody className='body' {...getTableBodyProps()}>
              {page.map((row, i) => {
                prepareRow(row);
                return (
                  <Fragment key={row.getRowProps().key}>
                    <tr className='tr' onClick={() =>   handleShow(row.original)}>
                      {row.cells.map((cell) => {
                        return (
                          <td className='td' {...cell.getCellProps()}>
                            {cell.render("Cell")}
                          </td>
                        );
                      })}
                    </tr>
                  </Fragment>
                );
              })}
            </tbody>

We have access to the row from the .map function where the table rows are created. In my example, I am using pagination, so what you're mapping over may be different. In any case, the row should be available to you.

The other properties available on the row are:

allCells: (12) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
cells: (12) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
depth: 0
getRowProps: ƒ (userProps)
id: "1"
index: 1
original: {processing_agent: "Smitty", log_id: "ASDJFEIF87ASDF", date_created: "2020-08-12 02:39:13+00:00", log_amount: "0.06", company_name: "Kinkos", …}
originalSubRows: []
subRows: []
values: {processing_agent: "Smitty", log_id: "ASDJFEIF87ASDF", company_name: "Kinkos", invoice_count: "1", merchant_log_status: "UNKNOWN", …}
__proto__: Object

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM