I got a table, filled by data coming from my API, I'm learning React and come to the solution in several tries.
Now I got the data printed in my table, but, these data is repeated three times (as the rows number multiplied by row number).
Here is my code:
import React from "react";
// reactstrap components
import {Card, CardHeader, CardBody, Row, Col, Breadcrumb, BreadcrumbItem, CardTitle, Button, Table} from "reactstrap";
// core components
import PanelHeader from "components/PanelHeader/PanelHeader.jsx";
class Registries extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoaded: false,
error: null,
articles: [],
};
}
componentDidMount() {
fetch('http://127.0.0.1:8004/api/articles/all/')
.then(results => {
return results.json();
})
.then(data => {
let articles = data.map((row) => {
return(
<tr key={row.id}>
<td>{row.id}</td>
<td>{row.name}</td>
<td>{row.category}</td>
<td style={{width:"106px"}}>
<Button size={"sm"} color={"warning"}>
<i className={"fa fa-edit"} />
</Button>
<Button size={"sm"} color={"danger"}>
<i className={"fa fa-trash"} />
</Button>
</td>
</tr>
)
});
this.setState({
isLoaded: true,
articles: articles
});
console.log(articles);
})
}
render() {
return (
<>
<PanelHeader size="sm" />
<div className="content">
<Row>
<Col xs={12}>
<Card>
<CardHeader>
<Breadcrumb>
<BreadcrumbItem>Home</BreadcrumbItem>
<BreadcrumbItem active>Articoli</BreadcrumbItem>
</Breadcrumb>
<Row>
<Col xs="10">
<CardTitle tag="h4">Articoli</CardTitle>
</Col>
<Col xs="2">
<Button icon="ui-1_simple-add" size="lg" color="success" outline className={"btn-block"}>
<i className={"fa fa-plus"} /> Nuovo
</Button>
</Col>
</Row>
</CardHeader>
<CardBody>
<Table data={this.state.articles} responsive className={"table-hover"}>
<thead className="text-primary">
<tr>
<th>ID</th>
<th>Nome</th>
<th>Categoria</th>
<th style={{width:"106px"}}>Opzioni</th>
</tr>
</thead>
<tbody>
{this.state.articles.map((prop, key) => {
if(this.state.error) {
return(<div>Error: {this.state.error.message}</div>);
}
else if(this.state.isLoaded === false) {
return(
<div>
<i className={"fa fa-spin fa-spinner"}/>
<br/>
Caricamento...
</div>
);
}
else if(this.state.articles) {
return (
<>
{this.state.articles.map((prop, key) => {
return <>{prop}</>;
})}
</>
);
}
})}
</tbody>
</Table>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
}
}
export default Registries;
Here is how the table looks like:
The goal is to get only 3 rows, as the API return
You are calling this.state.articles.map in another this.state.articles.map in your render function.
Try to refactor this part of code:
{this.state.articles.map((prop, key) => {
if(this.state.error) {
return(<div>Error: {this.state.error.message}</div>);
}
else if(this.state.isLoaded === false) {
return(
<div>
<i className={"fa fa-spin fa-spinner"}/>
<br/>
Caricamento...
</div>
);
}
else if(this.state.articles) {
return (
<>
{this.state.articles.map((prop, key) => {
return <>{prop}</>;
})}
</>
);
}
})}
One of possible refactorings could be like this:
{
this.state.error ?
(<div>Error: {this.state.error.message}</div>) :
(
this.state.isLoaded === false ?
(
<div>
<i className={"fa fa-spin fa-spinner"}/>
<br/>
Caricamento...
</div>
) :
(
this.state.articles && this.state.articles.map((prop, key) => {
return (<>{prop}</>);
})
)
)
}
Related
I have a table that can add and delete rows. However, am not able to validate the table. if the table cells are empty or filled am not able to post the values to the backend. The error message still shows.What is the best way to validate the table. I would like to have the error message show if the fields are empty on submit.
payment.js
import React, {Component } from "react";
import "bootstrap/dist/css/bootstrap.min.css"
import axios from "axios"
import SimpleReactValidator from "simple-react-validator"
import Box from '#mui/material/Box';
import Button from "#mui/material/Button";
import BillTable from "./billTable"
import $ from 'jquery'
class Payment extends Component {
constructor(){
super()
this.state = {
Bill:"",
billTable: [{
index: Math.random(),
serialNumber: "",
item:"",
cost:""}],
errorMessage: '',
}
this.validator = new SimpleReactValidator({autoForceUpdate: this,messages: {
default: 'Please enter this field!'
},element: message => <div style={{color: "red"}}>{message}</div>})
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleChange = (e) => {
if (["serialNumber", "item", "cost"].includes(e.target.name)) {
let billTable = [...this.state.billTable]
billTable[e.target.dataset.id][e.target.name] = e.target.value;
}
else {
this.setState({ [e.target.name]: e.target.value })
}
};
addNewRowPlan = () => {
this.setState((prevState) => ({
billTable: [...prevState.billTable, { index: Math.random(), serialNumber: "", item: "", cost:""}],
}));
}
deleteRow = (index) => {
this.setState({
billTable: this.state.billTable.filter((s, sindex) => index !== sindex),
});
}
clickOnDelete(record) {
this.setState({
billTable: this.state.billTable.filter(r => r !== record),
});
}
handleSubmit(event){
event.preventDefault()
if(this.validator.allValid()){
this.validator.hideMessages()
const billed = {
Bill:this.state.billTable
};
axios.post(`http://localhost:4000/bill`, billed,{
})
.then(response => {
console.log(response.data)
return $('.alert-success').show();
})
this.setState({
Bill:"",
})
}
else{
this.validator.showMessages()
this.forceUpdate()
return $('.alert-danger').show();
}
}
render() {
let {billTable} = this.state
return (
<div>
<div className="container">
<div className="form-div">
<h1>Billing</h1>
<Box component="form" onSubmit={this.handleSubmit} noValidate sx={{ mt: 1}} onChange={this.handleChange}>
<div className="row" style={{ marginTop: 20 }}>
<div className="col-sm-3"></div>
<div className="col-sm-12">
<div className="card">
<div className="card-header text-center">Bill</div>
<div className="card-body">
<div className="row">
<div className="col-sm-4">
</div>
</div>
<table>
<thead>
<tr>
<th>Serial #</th>
<th>Item</th>
<th>Cost</th>
</tr>
</thead>
<tbody>
<BillTable id="bill" add={this.addNewRowPlan.bind(this)} delete={this.clickOnDelete.bind(this)} billTable={billTable} />
{this.validator.message('bill',this.state.Bill,'required')}
</tbody>
</table>
</div>
</div>
</div>
<div className="col-sm-1"></div>
</div>
<Button
type="submit"
fullWidth
sx={{ mt: 3, mb: 2}}
>
<span>Submit</span>
</Button>
</Box>
</div>
</div>
</div>
);
}
}
export default Payment;
billTable.js
import React from "react"
const billTable = (props) => {
return (props.billTable.map((val, idx) => {
let serialNumber = `serialNumber-$${idx}`, item = `item-$${idx}`, cost = `cost-$${idx}`
return (
<tr key={val.index}>
<td>
<input type="text" name="serialNumber" data-id={idx} id={serialNumber} className="form-control" />
</td>
<td>
<input type="text" name="item" data-id={idx} id={item} className="form-control " />
</td>
<td>
<input type="text" name="cost" data-id={idx} id={cost} className="form-control"/>
</td>
<td>
{
idx===0?<button onClick={()=>props.add(idx)} type="button" className="btn btn-primary">Add Row</button>
: <button className="btn btn-danger" onClick={(() => props.delete(val))} >Delete Row</button>
}
</td>
</tr>
)
})
)
}
export default billTable
`````````````````````
How can i correct this code. Thank you in advance
So I have a screen where I am showing details of a Medical Appointment, I have shown booked services in a table using a map function. Each row in table has a booked service info and reject button and accept button. I want to open a modal when any reject button is clicked,however the issue is that whenever I click any reject button the same modal opens,in other words the item.serviceData.serviceTitle shows the same name no matter which item I reject in the table row.
Can someone pls tell what the issue is
class AppointmentDetails extends Component {
constructor(props) {
super(props);
this.state = {
BookedServices: [],
Details:[],
Reject_Modal: false,
Lab_note: "",
UpdatedStatus:[],
Status: "Pending Response",
updatedappointment: [],
};
this.toggleRejectModal = this.toggleRejectModal.bind(this);
}
componentDidMount() {
// const{appointmentdetails}=this.props.match.params;
const {details}=this.props.location.state;
console.log(details);
this.setState({ BookedServices: details.BookedServices });
this.setState({ Details: details });
Status: this.state.Status;
// this.setState({ UpdatedStatus: this.state.UpdatedStatus });
// console.log(this.state.BookedServices);
//map through the booked services and display the services
}
componentDidUpdate(prevProps) {
if (this.props.details !== prevProps.details) {
this.setState({
BookedServices: details.BookedServices,
Details: details,
UpdatedStatus: this.state.UpdatedStatus,
Status: this.state.Status,
});
}
}
toggleRejectModal() {
this.setState(prevState => ({
Reject_Modal: !prevState.Reject_Modal,
}));
}
render() {
// const { invoiceDetail } = this.props;
const{ BookedServices,Details, UpdatedStatus, Lab_note, Status, updatedappointment}=this.state;
// const UpdatedStatus} =this.state.UpdatedStatus;
// const{Details}=this.state;
return (
<React.Fragment>
<div className="page-content">
<Container fluid>
<Breadcrumbs title="Pending Appointments" breadcrumbItem="Appointment Detail" />
{!isEmpty(Details) && (
<Row>
<Col lg="12">
<Card>
<CardBody>
<div className="invoice-title">
<p className="float-end text-muted font-size-12">
Appointment # {Details.id}
</p>
<div className="mb-4">
<img src={lablogohere} alt="logo" height="35" />
</div>
</div>
<hr />
<Row>
<Col sm="6">
<address>
<strong>Patient Information:</strong>
<br />
{Details.PatientType==="Self"?
<div>
<h6 className="mt-2">Name : {Details.PatientData.name} </h6>
<h6>Gender : {Details.PatientData.Gender}</h6>
<h6>Contact : {Details.PatientData.contact_number}</h6>
<h6>Email : {Details.PatientData.email}</h6>
</div>
:
<div>
<h6>Name : {Details.name} </h6>
<h6>Gender : {Details.Gender}</h6>
<h6>Contact : {Details.contact}</h6>
<h6>Email : {Details.PatientData.email}</h6>
<h6>Age : {Details.age} </h6>
</div>
}
</address>
</Col>
<Col sm="6" className="text-sm-end">
<address className="mt-2 mt-sm-0">
<strong>Address:</strong>
<br />
{Details.PatientType==="Self"?
<h6>{Details.PatientData.address}</h6>
:
<h6>{Details.Address}</h6>
}
<br />
</address>
</Col>
</Row>
<Row>
<Col sm="6" className="mt-3">
<address>
<strong>Date:</strong>
<br />
{Details.ReqDate}
<br />
<br />
</address>
</Col>
{/* <Col sm="6" className="text-sm-end">
<address>
<strong>Payment Method:</strong>
<br />
{Details.PaymentType}
<br />
</address>
</Col> */}
</Row>
<Row>
<div>
<h6><strong>Patient Note:</strong></h6>
<p>{Details.Notes}</p>
</div>
</Row>
<div className="py-2 mt-3">
<Row>
<Col xs="6">
<h3 className="font-size-15 font-weight-bold">
Appointment summary
</h3>
</Col>
<Col xs="6">
<h6 className="font-size-15 text-end">PKR.{Details.Price}</h6>
</Col>
</Row>
</div>
<div className="table-responsive">
<Table className="table-nowrap">
<thead>
<tr>
<th className=" text-center">Service Name.</th>
<th className=" text-center">HomeSampling</th>
<th className=" text-center">Communication</th>
<th className=" text-center">Requested Date-Time</th>
<th className=" text-center">Status</th>
<th className="text-center">Actions</th>
</tr>
</thead>
<tbody>
{map(
BookedServices,
(item, key) => (
<tr key={key}>
<td className=" text-center">{item.ServiceData.ServiceTitle}</td>
{item.HomeSampling === true ? <td className=" text-center"><h6 style={{color:"green"}}>✓</h6></td >: <td className=" text-center"><h6 style={{color:"red"}}>X</h6></td>}
{item.Communication === true ? <td className=" text-center"><h6 style={{color:"green"}}>✓</h6></td>: <td className=" text-center"><h6 style={{color:"red"}}>X</h6></td>}
<td className=" text-center">{item.RequestedTime}</td>
<td className="text-center"> <Badge
bg="danger"
className={"font-size-12 badge-soft-warning bg-soft-warning rounded-pill"}
// color={row.badgeclass}
>
{item.BookedServiceStatus}
</Badge></td>
<td className="text-center">
<Button
color="primary"
size="sm"
className="btn-pill mx-2"
onClick={() => {
this.setState({ UpdatedStatus: [...UpdatedStatus, { BookedServiceStatus: 'Accepted', id: item.id, Lab_note:null}] });
// this.setState.UpdatedStatus( [...UpdatedStatus, {BookedServiceStatus: "Accepted", id: item.id }])
// console.log(this.state.UpdatedStatus)
this.state.UpdatedStatus.map((item, index) => {
console.log(item)
if (item.BookedServiceStatus == "Accepted") {
this.setState({Status: 'Accepted'},()=>{
console.log("Status when accepted",this.state.Status)})
} else {
this.setState({Status: 'Rejected'},()=>{
console.log("Status when rejected",this.state.Status)}
)
}
}
)
}}
>
Accept
</Button>
<Button
color="danger"
size="sm"
className="btn-pill mx-2"
// onClick={this.toggleRejectModal}
// onClick={() => this.toggleRejectModal()}
onClick={e => {
e.preventDefault();
this.toggleRejectModal();
}
}
>
Reject
</Button>
</td>
<Modal
isOpen={this.state.Reject_Modal}
toggle={this.toggleRejectModal}
scrollable={true} // to enable scrollable body
centered={true} //to center the modal vertically
backdrop={"static"} //to disable click outside the modal
size="md">
<ModalHeader className="text-center">Reject Appointment
<button
type="button"
onClick={() => this.setState({ Reject_Modal: false })}
className="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</ModalHeader>
<ModalBody>
<h6>Service Name: {item.ServiceData.ServiceTitle} </h6>
<h6>Requested Time: {item.RequestedTime} </h6>
<Row>
<Col md={12}>
<Formik
enableReinitialize={true}
initialValues={{
Lab_note:
(this.state && this.state.Lab_note) || "",
}}
validationSchema={Yup.object().shape({
Lab_note: Yup.string().required(
"Please Enter reason for rejection"
),
})}
onSubmit={values =>
{
this.setState({ Lab_note: values.Lab_note })
let x= this.state.Lab_note
console.log("x",x)
}}
// this.setState(prevState => ({
// BookedService: {
// ...prevState.BookedService,
// Lab_note: values.Lab_note,
// }
// ,
// }));
>
{({
errors,
status,
touched,
values,
setFieldValue,
}) => (
<Form id="Detail-form">
<div className="mb-3">
<Label className="control-label">
Note:
</Label>
<Field
name="Lab_note"
type="text"
component="textarea"
rows={3}
onChange={e => {
this.setState({
Lab_note: e.target.value,
}),
setFieldValue(
"Lab_note",
e.target.value
);
}}
className={
"form-control" +
(errors.Lab_note &&
touched.Lab_note
? " is-invalid"
: "")
}
placeholder="Enter Reason for Rejection"
/>
<ErrorMessage
name="Lab_note"
component="div"
className="invalid-feedback"
/>
</div>
</Form>
)}
</Formik>
</Col>
</Row>
<Row>
<Col className="text-end">
<button
type="submit"
className="btn"
style={{
backgroundColor: "red",
color: "white",
}}
onClick={() =>
{
this.setState({ UpdatedStatus: [...UpdatedStatus, { BookedServiceStatus: 'Rejected', id: item.id, Lab_note:this.state.Lab_note}] });
// this.setState({ UpdatedStatus: [...UpdatedStatus, { BookedServiceStatus: 'Rejected', id: item.id, Lab_note:this.state.Lab_note}] });
// this.setState((state)=>
// ({ UpdatedStatus: state.UpdatedStatus.concat({ BookedServiceStatus: 'Rejected', id: item.id ,Lab_note:this.state.Lab_note })}
// ));
this.setState({ Reject_Modal: false })
this.setState({Lab_note: ""})
this.state.UpdatedStatus.map((item, index) => {
console.log(item)
if (item.BookedServiceStatus == "Accepted") {
this.setState({Status: 'Accepted'},()=>{
console.log("Status when accepted",this.state.Status)})
} else {
this.setState({Status: 'Rejected'},()=>{
console.log("Status when rejected",this.state.Status)}
)
}
}
)
}
}
>
Reject
</button>
</Col>
</Row>
</ModalBody>
</Modal>
</tr>
)
)}
</tbody>
</Table>
</div>
<div className="d-print-none">
<Row>
<Col lg="9">
</Col>
<Col lg="3" className="text-center">
<Button
color="success"
onClick={e=>{
e.preventDefault();
// this.state.UpdatedStatus.map((item, index) => {
// console.log(item)
// if (item.BookedServiceStatus == "Accepted") {
// this.setState({Status: 'Accepted'},()=>{
// console.log("Status when accepted",this.state.Status)})
// } else {
// this.setState({Status: 'Rejected'},()=>{
// console.log("Status when rejected",this.state.Status)}
// )
// }
// }
// )
this.props.onUpdateStatus(this.state.Status,this.state.UpdatedStatus, Details.id)}}
className="btn btn-success w-md mr-6"
>
Respond
</Button>
</Col>
</Row>
{/* <div className="float-end mr-5">
<Link
to="#"
className="btn btn-success w-md mr-4"
>
Respond
</Link>
</div> */}
</div>
</CardBody>
</Card>
</Col>
</Row>
)}
</Container>
</div>
{console.log(this.state.UpdatedStatus)}
</React.Fragment>
);
}
}
I'm studying about react, I've made a form to save data with react,
I want to update the table again as data is saved, I've used setState for this purpose, The issue is state updating but not rendering, I've tried some ways to find the issue,
by using console.log() it is found that the state is properly changing
render function is properly working after changing state
here's my code
import React, { Component } from "react";
import Header from "../header";
import Table from "./table";
import Addbox from "./create__box";
import $ from "jquery";
import { Api__url } from "../../vars";
class index extends Component {
constructor(props) {
super(props);
// binding functions
this.getData = this.getData.bind(this);
this.table = this.table.bind(this);
this.show_create_box = this.show_create_box.bind(this);
// using state
this.state = {
data: "Fetching Records....",
create_box: "",
};
}
getData() {
$.ajax({
type: "POST",
url: `${Api__url}services/get`,
dataType: "JSON",
success: this.table,
});
}
table(d) {
this.setState({ data: <Table data={d} /> });
}
show_create_box() {
this.setState({create_box: <Addbox top="15vh" again_get_data={this.getData}/>});
}
componentDidMount() {
this.getData();
}
render() {
return (
<>
<Header />
<div className="container mt-5 px-5">
<div className="border__box p-2 col">
<div className="row m-0 px-3">
<div className="col">
<h2>Services in home page</h2>
</div>
<div className="col d-flex justify-content-end">
<button
onClick={this.show_create_box}
className="btn btn-outline-success show__create__box"
>
Add New Data
</button>
</div>
</div>
<div className="row m-0 py-2 px-4">{this.state.data}</div>
</div>
</div>
{this.state.create_box}
</>
);
}
}
export default index;
```
the code from the table file
```
import React, { Component } from "react";
import Updatebox from "./update__box";
class table extends Component {
constructor(props) {
super(props);
this.show_update_box = this.show_update_box.bind(this);
this.delete_record = this.delete_record.bind(this);
this.state = { update_box: "" };
// making data
this.tbody = props.data.map((d, index) => {
return (
<tr className="w-100 row m-0 p-0" id={d.services_id}>
<th className="col-1" scope="row">
{index + 1}
</th>
<td className="col-3">{d.services_name}</td>
<td className="col-4">{d.services_description}</td>
<td className="col-2">{d.services_icon}</td>
<td className="col-1">
<button
onClick={() => {
this.show_update_box(index);
}}
className="btn btn-outline-success"
>
Update
</button>
</td>
<td className="col-1">
<button
onClick={() => {
this.delete_record(index);
}}
className="btn btn-outline-danger"
>
Delete
</button>
</td>
</tr>
);
});
}
// Function to get close form instruction from another class
changeStuff(d) {
this.setState(d);
}
delete_record(id) {
alert(id);
}
show_update_box(key) {
this.setState({
update_box: (
<Updatebox
data={this.props.data[key]}
changeHandler={this.changeStuff.bind(this)}
/>
),
});
}
render() {
return (
<>
<table className="position-relative table table-hover ">
<thead className="table-dark">
<tr className="row m-0 p-0">
<th className="col-1">Sr #</th>
<th className="col-3">Name</th>
<th className="col-4">Description</th>
<th className="col-2">Icon</th>
<th className="col-1">Update</th>
<th className="col-1">Delete</th>
</tr>
</thead>
<tbody>{this.tbody}</tbody>
</table>
{this.state.update_box}
</>
);
}
}
export default table;
```
here's the code for creating the box
```
import React, { Component } from "react";
import CloseIcon from "#mui/icons-material/Close";
import $ from "jquery";
// import i from "./index";
export default class Addbox extends Component {
constructor(props) {
super(props);
this.data = { name: "", description: "", icon: "" };
this.state = this.data;
this.change = this.change.bind(this);
this.submit = this.submit.bind(this);
this.changeCSS = this.changeCSS.bind(this);
this.setCSS = this.setCSS.bind(this);
this.close_create_box = this.close_create_box.bind(this);
}
close_create_box() {
this.props.changeHandler({ create_box: "" });
}
change(e) {
var name = e.target.name;
var value = e.target.value;
this.setState({
[name]: value,
});
}
changeCSS() {
$("#create").removeClass("btn-outline-success");
$("#create").addClass("btn-outline-dark");
$("#create").prop("disabled", true);
$("#create").text("Sending....");
}
setCSS() {
$("#create").removeClass("btn-outline-dark");
$("#create").addClass("btn-outline-success");
$("#create").prop("disabled", false);
$("#create").text("Submit");
}
submit(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: "http://127.0.0.1:8000/api/services/create",
data: this.state,
dataType: "JSON",
beforeSend: this.changeCSS,
success: (e) => {
alert(e.message);
this.props.again_get_data();
this.close_create_box();
},
error: (e) => {
this.setCSS();
alert(e.responseText);
},
});
}
render() {
return (
<form
onSubmit={this.submit}
className="add__box create__box"
method="POST"
style={{ top: this.props.top }}
>
<div className="mb-3 row">
<div className="col-10">
<h4>Add New Service</h4>
</div>
<div className="col-2">
<CloseIcon className="close" onClick={this.close_create_box} />
</div>
</div>
<div className="mb-3">
<label htmlFor="create_name" className="form-label">
Name
</label>
<input
id="create_name"
name="name"
type="text"
className="form-control"
onChange={this.change}
value={this.state.name}
required
minLength={10}
maxLength={100}
/>
</div>
<div className="mb-3">
<label htmlFor="create_desc" className="form-label">
Description
</label>
<textarea
id="create_desc"
className="form-control"
onChange={this.change}
required
value={this.state.description}
minLength={20}
name="description"
></textarea>
</div>
<div className="mb-3">
<label htmlFor="create_icon" className="form-label">
Icon
</label>
<input
id="create_icon"
type="text"
className="form-control"
onChange={this.change}
value={this.state.icon}
required
name="icon"
/>
</div>
<div className="m-5 row my-0">
<button id="create" type="submit" className="btn btn-outline-success">
Submit
</button>
</div>
</form>
);
}
}
```
as per react docs, UI components shouldn't be in state and it should only contain the minimal amount of data needed to represent your UI's state.
so instead of adding a UI element in the state, you should just add a minimal amount of data in it
Here's an example based on your code
constructor(props) {
...
this.state = {
status: "loading",
data: "Fetching Records....",
create_box: "",
};
}
table(d) {
this.setState({ data: d, status: "table" });
}
renderData() {
const d = this.state.data
const status = this.state.status
if (status == "loading") { return d }
if (status == "table") { return <Table data={d} /> }
}
render() {
return (
<>
...
<div className="row m-0 py-2 px-4">{renderData()}</div>
...
</>
);
}
I'm new in React and I have to create a CRUD table for my DB.
I created a simple table as you can see:
class ListPromoCatalog extends React.Component {
constructor(props) {
super(props);
this.state = {
promos: [],
message: null
};
this.refreshPromo = this.refreshPromo.bind(this)
}
componentDidMount() { //React defines a component lifecycle
this.refreshPromo();
}
refreshPromo() {
PromoCatalogService.retrieveAllPromo(PRIZES)//this would make the call to the REST API.
.then(
response => {
console.log(response);
this.setState({promos: response.data.viaggio})
}
)
}
PromoOffClicked(id) {
PromoCatalogService.promoOff(PRIZES, id)
.then(
response => {
console.log(response);
this.setState({message: `Promo ${id} OFF Successful`});
this.refreshPromo();
}
)
}
updatePromoClicked(id) {
console.log('update ' + id);
this.props.history.push(`/promos/${id}`);
}
addCourseClicked() {
this.props.history.push(`/promos/-1`);
}
render() {
return (
<div className="container">
<h3>All Promo</h3>
<div className="row">
<FileUploader/>
</div>
{this.state.message && <div className="alert alert-success">{this.state.message}</div>}
<div className="container">
<table className="table">
<thead>
<tr>
<th>Id</th>
<th>Item</th>
<th>Title</th>
<th>Description</th>
<th>Delete</th>
<th>Update</th>
</tr>
</thead>
<tbody>
{
this.state.promos.map(
promo =>
<tr key={promo.promoId}>
<td>{promo.promoId}</td>
<td>{promo.ijCod}</td>
<td>{promo.title}</td>
<td>{promo.description}</td>
<td>
<button className="btn btn-warning"
onClick={() => this.PromoOffClicked(promo.promoId)}>OFF
</button>
</td>
<td>
<button className="btn btn-success"
onClick={() => this.updatePromoClicked(promo.promoId)}>Update
</button>
</td>
</tr>
)
}
</tbody>
</table>
<div className="row">
<button className="btn btn-success" onClick={this.addCourseClicked}>Add</button>
</div>
</div>
</div>
)
}
}
export default ListPromoCatalog
I would like to do the same thing with a Material Table but I don't know how to put data and methods in my new class.
I would like to do the same thing with a Material Table but I don't know how to put data and methods in my new class.
render() {
return (
<>
<PanelHeader size="sm"/>
<div className="content">
<Row>
<Col xs={12}>
<Card>
<CardHeader>
<CardTitle tag="h4">Simple Table</CardTitle>
</CardHeader>
<CardBody>
<MDBDataTable
striped
bordered
small
data={data} //DATA SHOULD CONTAIN HEADERS AND COLUMNS
/>
</CardBody>
</Card>
</Col>
</Row>
</div>
</>
);
}
My aim is to have my modal dialog box pop up on click. However, I receive this error every time I execute:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem
May I have some direction on where I am going wrong with this?
import React from 'react';
import { connect } from 'react-redux';
import { myActions } from './actions/my.actions';
import { Modal, Button } from 'react-bootstrap';
class LoadTable extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
Search: "Search",
visible: false
}
this.doSearch = this.doSearch.bind(this);
this.handleShow = this.handleShow.bind(this);
this.handleClose = this.handleClose.bind(this);
this.runstuff = this.runstuff(this);
}
componentDidMount() {
this.props.getstuff()
.then((res) => {
this.setState({
data: res.results.response || [], <--IT shows in the error that it breaks here.
visible: false
})
});
}
doSearch(e) {
const { name, value } = e.target;
this.setState({ [name]: value });
console.log("Search");
}
handleShow() {
this.setState({ visible: true });
}
handleClose() {
this.setState({ visible: false });
}
runstuff() {
}
render() {
const { data, Search } = this.state;
return data.length > 0 ? (
<div className="row row-centered">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-centered">
<div id="Search" className="row col-xs-5 col-lg-2">
<div className="form-group">
<input className='form-control' type="text" placeholder="Search" name="Search" value={Search} onChange={this.doSearch} autoFocus />
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<td>Name</td>
<td>stuff</td>
<td>Start</td>
<td>End</td>
<td>Status</td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
{
data.map((dt) => {
return (
<tr>
<td>{dt.name}</td>
<td>{dt.stuff}</td>
<td>{dt.start}</td>
<td>{dt.end}</td>
{ dt.status ?
<td>
<div className="alert alert-success" role="alert"></div>
</td>
:
<td>
<div className="alert alert-danger" role="alert"></div>
</td>
}
<td><button type="button" className="btn btn-primary" onClick={this.runStuff}>Run Stufff</button></td>
<td><button type="button" className="btn btn-info" onClick={this.displayLog}><View Stuff</button></td>
<Modal
show={this.state.visible}
onHide={this.handleClose}
>
<Modal.Header closeButton>
<Modal.Title>Run Stuff for Stuff</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>{dt.lotsofstuff}</div>
</Modal.Body>
<Modal.Footer>
<Button
variant="secondary"
onClick={this.handleClose}
>
Close
</Button>
<Button variant="primary" onClick={this.handleClose}>
Download
</Button>
</Modal.Footer>
</Modal>
</tr>
);
})
}
</tbody>
</table>
</div>
</div>
) :
<div className="row">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>No Data to Display at the moment</p>
</div>
</div>;
}
}
function mapStateToProps(state) {
return {
};
}
const mapDispatchToProps = dispatch => ({
getstuff: () => dispatch(myActions.getstuff())
});
export default connect(mapStateToProps, mapDispatchToProps)(myLoad);