问题
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;
回答1:
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
}
回答2:
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
来源:https://stackoverflow.com/questions/59806312/passing-react-table-row-data-to-react-modal