I am trying to develop a simple React app, with crud operations, but I can't even list my objects, which are stored into a sql database. I followed this example for the frontend: https://github.com/only2dhir/react-js-example
and I continued it, adding the component for my objects.
In my application, I have doctors and patients. A patient is assigned to a doctor, so a doctor can have one or more patients. In order to do this, I create my jsx file, ListCaregiverComponent.jsx, where I did that :
import React, { Component } from 'react'
import ApiServiceCaregiver from "../../service/ApiServiceCaregiver";
import ApiServicePatient from "../../service/ApiServicePatient";
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import Typography from '#material-ui/core/Typography';
class ListCaregiverComponent extends Component {
constructor(props) {
super(props)
this.state = {
caregivers: [],
patients: [],
message: null
}
this.deleteCaregiver = this.deleteCaregiver.bind(this);
this.editCaregiver = this.editCaregiver.bind(this);
this.addCaregiver = this.addCaregiver.bind(this);
this.reloadCaregiverList = this.reloadCaregiverList.bind(this);
this.reloadPatientList = this.reloadPatientList.bind(this);
}
componentDidMount() {
this.reloadCaregiverList();
this.reloadPatientList();
}
reloadCaregiverList() {
ApiServiceCaregiver.fetchCaregivers()
.then((res) => {
this.setState({caregivers: res.data.result})
});
}
reloadPatientList() {
ApiServicePatient.fetchPatients()
.then((res) => {
this.setState({patients: res.data.result})
});
}
deleteCaregiver(userId) {
ApiServiceCaregiver.deleteCaregiver(userId)
.then(res => {
this.setState({message : 'User deleted successfully.'});
this.setState({caregivers: this.state.caregivers.filter(user => user.id !== userId)});
})
}
editCaregiver(id) {
window.localStorage.setItem("userId", id);
this.props.history.push('/edit-caregiver');
}
addCaregiver() {
window.localStorage.removeItem("userId");
this.props.history.push('/add-caregiver');
}
render() {
return (
<div>
<br></br>
<br></br>
<Typography variant="h4" style={style}>Caregiver Details</Typography>
<br></br>
<br></br>
<Table>
<TableHead>
<TableRow>
<TableCell>Id</TableCell>
<TableCell align="right">Name</TableCell>
<TableCell align="right">Birth Date</TableCell>
<TableCell align="right">Gender</TableCell>
<TableCell align="right">Address</TableCell>
<TableCell align="center">Patients</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.caregivers.map(({ id, name, birthDate, gender, address, patients = [] }) =>(
<TableRow key={id}>
<TableCell component="th" scope="row">
{id}
</TableCell>
<TableCell align="right">{name}</TableCell>
<TableCell align="right">{birthDate}</TableCell>
<TableCell align="right">{gender}</TableCell>
<TableCell align="right">{address}</TableCell>
<TableCell align="right">
<TableRow>
<TableCell align = "right" >Id</TableCell>
<TableCell align = "right" >Name</TableCell>
<TableCell align="right">Birth Date</TableCell>
<TableCell align="right">Gender</TableCell>
<TableCell align="right">Address</TableCell>
<TableCell align="right">Medical Record</TableCell>
</TableRow>
{patients.map(({ id, name, birthDate, gender, address, medicalRecord })=> {
return (
<TableRow key={id}>
<TableCell component="th" scope="row">
{id}
</TableCell>
<TableCell align="right">{name}</TableCell>
<TableCell align="right">{birthDate}</TableCell>
<TableCell align="right">{gender}</TableCell>
<TableCell align="right">{address}</TableCell>
<TableCell align="right">{medicalRecord}</TableCell>
</TableRow>
)
})}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
}
const style ={
display: 'flex',
justifyContent: 'center'
}
export default ListCaregiverComponent;
The ListPatientComponent.jsx looks like this :
import React, { Component } from 'react'
import ApiServicePatient from "../../service/ApiServicePatient";
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import Typography from '#material-ui/core/Typography';
class ListPatientComponent extends Component {
constructor(props) {
super(props)
this.state = {
patients: [],
message: null
}
this.deletePatient = this.deletePatient.bind(this);
this.editPatient = this.editPatient.bind(this);
this.addPatient = this.addPatient.bind(this);
this.reloadPatientList = this.reloadPatientList.bind(this);
}
componentDidMount() {
this.reloadPatientList();
}
reloadPatientList() {
ApiServicePatient.fetchPatients()
.then((res) => {
this.setState({patients: res.data.result})
});
}
deletePatient(userId) {
ApiServicePatient.deletePatient(userId)
.then(res => {
this.setState({message : 'User deleted successfully.'});
this.setState({patients: this.state.patients.filter(user => user.id !== userId)});
})
}
editPatient(id) {
window.localStorage.setItem("userId", id);
this.props.history.push('/edit-patient');
}
addPatient() {
window.localStorage.removeItem("userId");
this.props.history.push('/add-patient');
}
render() {
return (
<div>
<br></br>
<br></br>
<Typography variant="h4" style={style}>Patient Details</Typography>
<br></br>
<br></br>
<Table>
<TableHead>
<TableRow>
<TableCell>Id</TableCell>
<TableCell align="right">Name</TableCell>
<TableCell align="right">Birth Date</TableCell>
<TableCell align="right">Gender</TableCell>
<TableCell align="right">Address</TableCell>
<TableCell align="right">Medical Record</TableCell>
<TableCell align="center">Medication Plans</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.patients.map(row => (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
{row.id}
</TableCell>
<TableCell align="right">{row.name}</TableCell>
<TableCell align="right">{row.birthDate}</TableCell>
<TableCell align="right">{row.gender}</TableCell>
<TableCell align="right">{row.address}</TableCell>
<TableCell align="right">{row.medicalRecord}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
}
const style ={
display: 'flex',
justifyContent: 'center'
}
export default ListPatientComponent;
and it works.
I also added two new js files, ApiServicePatient.js and ApiServiceCaregiver.js :
import axios from 'axios';
const CAREGIVER_API_BASE_URL = 'http://localhost:8080/caregivers';
class ApiServiceCaregiver {
fetchCaregivers() {
return axios.get(CAREGIVER_API_BASE_URL);
}
fetchCaregiverById(caregiverId) {
return axios.get(CAREGIVER_API_BASE_URL + '/' + caregiverId);
}
deleteCaregiver(caregiverId) {
return axios.delete(CAREGIVER_API_BASE_URL + '/' + caregiverId);
}
addCaregiver(caregiver) {
return axios.post(""+CAREGIVER_API_BASE_URL, caregiver);
}
editCaregiver(caregiver) {
return axios.put(CAREGIVER_API_BASE_URL + '/' + caregiver.id, caregiver);
}
}
export default new ApiServiceCaregiver();
import axios from 'axios';
const PATIENT_API_BASE_URL = 'http://localhost:8080/patients';
class ApiServicePatient {
fetchPatients() {
return axios.get(PATIENT_API_BASE_URL);
}
fetchPatientById(userId) {
return axios.get(PATIENT_API_BASE_URL + '/' + userId);
}
deletePatient(userId) {
return axios.delete(PATIENT_API_BASE_URL + '/' + userId);
}
addPatient(user) {
return axios.post(""+PATIENT_API_BASE_URL, user);
}
editPatient(user) {
return axios.put(PATIENT_API_BASE_URL + '/' + user.id, user);
}
}
export default new ApiServicePatient();
Also, in App.js, I added :
import React from 'react';
import './App.css';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import ListUserComponent from "./component/user/ListUserComponent";
import AddUserComponent from "./component/user/AddUserComponent";
import EditUserComponent from "./component/user/EditUserComponent";
import ListPatientComponent from "./component/patient/ListPatientComponent";
import ListCaregiverComponent from "./component/caregiver/ListCaregiverComponent";
function App() {
return (
<div className="container">
<Router>
<div className="col-md-6">
<h1 className="text-center" style={style}>React User Application</h1>
<Switch>
<Route path="/" exact component={ListUserComponent} />
<Route path="/users" component={ListUserComponent} />
<Route path="/add-user" component={AddUserComponent} />
<Route path="/edit-user" component={EditUserComponent} />
<Route path="/patients" component={ListPatientComponent} />
<Route path="/caregivers" component={ListCaregiverComponent} />
</Switch>
</div>
</Router>
</div>
);
}
const style = {
color: 'red',
margin: '10px'
}
export default App;
It doesn't work, it only says :
Unhandled Rejection (TypeError): Cannot read property 'map' of undefined
and it indicates the lines with :
<TableCell align="right">{row.address}</TableCell>
{row.patients.map(row => (
In the backend application, the class Caregiver has a list of patients objects, mapped as one-to-many :
#OneToMany(mappedBy = "caregiver", fetch = FetchType.EAGER)
private List<Patient> patients;
Does anyone have some suggestions?
--------UPDATE AFTER FIRST ANSWERS---------
I no longer get that error, but I can't display in my table of caregivers the assigned patients. The corresponding TableCell s are empty for the patients of each caregiver. Why is happening this?
You do this.state.caregivers.map(row => and then {row.patients.map(row =>, but I don't see any indication that each caregivers element has a patients array property
Since you are using asynchronous call the javascript start rendering and for a few miliseconds "this.state.caregivers" has no value so you cannot map a null value it needs to be array null.
Make sure to add a condition to check first or declare "this.state.caregivers" as empty array in the constructor.
As mentioned in other answers, patients is maybe undefined for some rows, so you could assign it a default value using Destructuring:
{this.state.caregivers.map(({ id, name, birthDate, gender, address, patients = [] }) => (
<TableCell component="th" scope="row">
{id}
</TableCell>
<TableCell align="right">{name}</TableCell>
<TableCell align="right">{birthDate}</TableCell>
<TableCell align="right">{gender}</TableCell>
<TableCell align="right">{address}</TableCell>
{patients.map(row => (
...
Try to add before each map the property you want to map and && like this:
this.state.caregivers && this.state.caregivers.map
Do this for each map in your code.
Related
This is my component here I'm using MUI for table. I'm getting data from API and I also use map method to get my data but I'm getting error that says:
TypeError: language.map is not a function
But when put language in square it does not error but also not show any data on UI according to me my code is correct can anyone help me.
Language.js
import Table from "#mui/material/Table";
import TableBody from "#mui/material/TableBody";
import TableCell from "#mui/material/TableCell";
import TableContainer from "#mui/material/TableContainer";
import TableHead from "#mui/material/TableHead";
import TableRow from "#mui/material/TableRow";
import Paper from "#mui/material/Paper";
import axios from "axios";
import { useState, useEffect } from "react";
const Languages = () => {
const [language, setLanguage] = useState([]);
useEffect(() => {
axios
.get(
"https://omxdgcc23c.execute-api.ap-south-1.amazonaws.com/dev/api/misc/languages?
userId=0x60588910"
)
.then((res) => {
console.log(res.data);
setLanguage(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<div>
<h1>Languages</h1>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>Id</TableCell>
<TableCell align="right">English Text</TableCell>
<TableCell align="right"> Text</TableCell>
<TableCell align="right">Category</TableCell>
<TableCell align="right">Order Index</TableCell>
<TableCell align="right">Language Code</TableCell>
<TableCell align="right">Created Time</TableCell>
<TableCell align="right">Updated Time</TableCell>
</TableRow>
</TableHead>
<TableBody>
{language.map((languages) => {
return (
<TableRow key={languages.id}>
<TableCell component="th" scope="row">
{languages.uid}
</TableCell>
<TableCell align="right">{languages.engText}</TableCell>
<TableCell align="right">{languages.text}</TableCell>
<TableCell align="right">{languages.category}</TableCell>
<TableCell align="right">{languages.index}</TableCell>
<TableCell align="right">{languages.code}</TableCell>
<TableCell align="right">{languages.createdAt}</TableCell>
<TableCell align="right">{languages.updatedAt}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</div>
);
};
export default Languages;
See the axios API here, the fetched data is also stored in the data property, so you have to access it like this:
axios.get('...').then(res => setLanguage(res.data.data));
Check the length of language state, if it is greater than 0 after only you can map the language array,
Kindly, check with below code,
{ language && language.length > 0 && language.map((languages) => {
return (
<TableRow key={languages.id}>
<TableCell component="th" scope="row">
{languages.uid}
</TableCell>
<TableCell align="right">{languages.engText}</TableCell>
<TableCell align="right">{languages.text}</TableCell>
<TableCell align="right">{languages.category}</TableCell>
<TableCell align="right">{languages.index}</TableCell>
<TableCell align="right">{languages.code}</TableCell>
<TableCell align="right">{languages.createdAt}</TableCell>
<TableCell align="right">{languages.updatedAt}</TableCell>
</TableRow>
);
})}
The api response is of the format:
{
"statusCode": 200,
"data": [
{...},
{...}
]
}
So when setting languages you need to save the data property of the response's data object.
setLanguage(_.get(res, 'data.data', []));
Then, languages will always be a list, and you won't need to check it throughout the rest of your function.
You may need to check the response in your useEffect block if you want to do some error handling against a bad api response. But that's now in one place rather than throughout the rest of the function.
I have a problem with the management of the data, when i try to render some data from the pokemon api my table render multiple times the titles, i tried to move only the data to a different component but not luck.
How can i fix this?
API CAll
export const PokemonApi = () => {
const [poke, setPoke] = useState([]);
const data = () => {
axios.get('https://pokeapi.co/api/v2/pokemon?limit=10&offset=20').then(( response ) => {
setPoke(response.data.results);
console.log(response.data.results);
})
.catch( err => {
console.log(err);
})
}
useEffect(() => {
data()
}, []);
return (
<>
{
poke.map(( info, name ) => {
return <Lista key={ name } info={ info } />
})
}
</>
)
}
component where I try to render
export const Lista = (props) => {
const classes = useStyles();
return (
<div>
<Container maxWidth="md">
<TableContainer component={Paper}>
<Table className={ classes.table } size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell align="right">URL</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow key={ props.info.name }>
<TableCell component="th" scope="row">
{ props.info.name }
</TableCell>
<TableCell align="right">{ props.info.url }</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Container>
</div>
)
}
This is the page where i render the table
import React from 'react'
import { PokemonApi } from '../api/PokemonApi'
export const Pokes = () => {
return (
<>
<PokemonApi />
</>
)
}
And here is the table.
I hope anyone can help me!
As your code is written, you are not rendering one table with a row for each line. You are creating one Lista par record, you have as many tables as pokemon.
What you are looking to achieve is more like :
function PokemonRow(props) {
return (
<TableRow key={ props.info.name }>
<TableCell component="th" scope="row">
{ props.info.name }
</TableCell>
<TableCell align="right">{ props.info.url }</TableCell>
</TableRow>
)
}
export const PokemonTable() {
const classes = useStyles();
const [poke, setPoke] = useState([]);
const data = () => {
axios.get('https://pokeapi.co/api/v2/pokemon?limit=10&offset=20').then(( response ) => {
setPoke(response.data.results);
console.log(response.data.results);
})
.catch( err => {
console.log(err);
})
}
useEffect(() => {
data()
}, []);
return (
<div>
<Container maxWidth="md">
<TableContainer component={Paper}>
<Table className={ classes.table } size="small" aria-label="a dense table">
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell align="right">URL</TableCell>
</TableRow>
</TableHead>
<TableBody>
{poke.map(infos => <PokemonRow info={infos}/>)}
</TableBody>
</Table>
</TableContainer>
</Container>
</div>
)
}
When the user clicks the tableCell text below, he should be navigated to http://localhost:3000/crayons/${rows.id} <- This exists in my react-router-dom
I am not sure how to edit the below code to do the following
<TableBody>
{props.rows.slice(page).map(row => (
<TableCell align="center">{row.crayon_color}</TableCell>
</TableBody>
What I tried
<TableCell align="center" numeric component="a" href=`http://localhost:3000/crayons/${rows.id}`> {row.crayon_color}</TableCell>
Try using a callback for the table cell that pushes the routes into history, so with that your code would resemble something like this:
import React from 'react';
import {withRouter} from 'react-router-dom';
const ExampleComponent = (props) => {
// ...other component variables
callback = () => {
props.history.push(`crayons/${rows.id}`)
}
return (
<TableCell align="center" onClick={callback}>{row.crayon_color}</TableCell>
);
}
export default withRouter(ExampleComponent);
EDIT updated live demo to show how to handle dynamic objects in an array.
EDIT 2 updated live demo and the code below to reflect how to use URL params with dynamic objects..
I believe the easiest way to accomplish this is by using a <Link/> component from react-router-dom.
Live Demo Found Here
This is what the BrowserRouter needs to look like:
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/crayons" component={Crayons} />
<Route path="/crayons/:id" component={Crayons} />
{/* MUST BE THE LAST ROUTE IN THIS LIST!!!! */}
<Route component={FourZeroFour} />
</Switch>
Then inside of your Crayons.js page, you can access the URL param, in this case id like: props.match.params.id..
Demo Table code:
// Build 'fake data' for table
const rows = Array.from(Array(10).keys()).map(item => {
return {
data: "Crayon",
count: Math.floor(Math.random() * 100),
id: item + 1
}
})
export default function Home() {
const classes = useStyles();
return (
<>
<h1>Welcome to my app</h1>
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>Data</TableCell>
<TableCell>ID</TableCell>
<TableCell>Count</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => {
return (
<TableRow key={row.id}>
<TableCell component="th" scope="row">
{row.id
? <Link to={`/crayons/${row.id}`}>{row.data}</Link>
: row.data}
</TableCell>
<TableCell>
{row.id}
</TableCell>
<TableCell>
{row.count}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
</Paper>
</>
)
}
You can use library React Router Dom.
Solution is simple add withRouter HOC to your component.
import { withRouter } from 'react-router-don'
const Component = () => (
<TableCell align="centre" onClick={()=>props.history.push(`${rows.id}`)}>{row.crayon_color}</TableCell>
)
export default withRouter(Component);
I have this section of a component I want to move apart and keep its props working. The way it is below works when it is within the parent component.
<TableExpandedRow key={rowExpanded.id}>
<TableCell colSpan={headers.length + 1}>
<div>
{rowExpanded &&
rowExpanded.billingItems &&
rowExpanded.billingItems.map(
item =>
rowExpanded.id ===
item.cancellationRequestId && (
<div key={item.id}>
<p>
cancellationRequestId:{' '}
{item.cancellationRequestId}
</p>
</div>
),
)}
</div>
</TableCell>
</TableExpandedRow>
So I want to make a component like this
import React from 'react';
import PropTypes from 'prop-types';
import { DataTable } from 'carbon-components-react';
const { TableExpandedRow, TableCell } = DataTable;
const TableExpandedRowComp = ({ rowExpanded, rowExpandedId, itemId, headersLength, keyId }) => (
<TableExpandedRow key={keyId}>
<TableCell colSpan={headersLength}>
<div>
{rowExpanded &&
rowExpanded.billingItems &&
rowExpanded.billingItems.map(
item =>
rowExpanded.id === item.cancellationRequestId && (
<div key={item.id}>
<p>cancellationRequestId: {item.cancellationRequestId}</p>
</div>
),
)}
</div>
</TableCell>
</TableExpandedRow>
);
TableExpandedRow.propTypes = {
rowExpanded: PropTypes.object,
headersLength: PropTypes.array,
keyId: PropTypes.object,
};
export default TableExpandedRowComp;
And then import it at where it was before like: <TableExpandedRow {...props} />
The whole component looks like this, it is a datable:
import React from 'react';
import PropTypes from 'prop-types';
import { translate } from 'react-i18next';
import { DataTable } from 'carbon-components-react';
import TableHeaders from '../TableHeaders';
import TablePagination from '../TablePagination';
import TableToolbarComp from '../TableToolbarComp';
const {
TableContainer,
TableRow,
TableExpandHeader,
TableExpandRow,
TableExpandedRow,
Table,
TableHead,
TableHeader,
TableBody,
TableCell,
} = DataTable;
function CancellationsTable({ t, tableRows }) {
return (
<div>
<DataTable
rows={tableRows}
headers={TableHeaders(t)}
render={({ rows, headers, getHeaderProps, getRowProps }) => (
<TableContainer>
<TableToolbarComp />
<Table zebra={false} short>
<TableHead>
<TableRow>
<TableExpandHeader />
{headers.map(header => (
<TableHeader {...getHeaderProps({ header })}>
{header.header}
</TableHeader>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.map(row => (
<React.Fragment key={row.id}>
<TableExpandRow {...getRowProps({ row })}>
{row.cells.map(cell => (
<TableCell key={cell.id}>{cell.value}</TableCell>
))}
</TableExpandRow>
{row.isExpanded &&
tableRows.map(
rowExpanded =>
row.id === rowExpanded.id && (
// THIS IS THE COMPONENT I WANT TO MOVE APART
<TableExpandedRow key={rowExpanded.id}>
<TableCell colSpan={headers.length + 1}>
<div>
{rowExpanded &&
rowExpanded.billingItems &&
rowExpanded.billingItems.map(
item =>
rowExpanded.id ===
item.cancellationRequestId && (
<div key={item.id}>
<p>
cancellationRequestId:{' '}
{item.cancellationRequestId}
</p>
</div>
),
)}
</div>
</TableCell>
</TableExpandedRow>
),
)}
</React.Fragment>
))}
</TableBody>
</Table>
</TableContainer>
)}
/>
</div>
);
}
CancellationsTable.propTypes = {
t: PropTypes.func.isRequired,
tableRows: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
};
export default translate()(CancellationsTable);
Any help?
I think that you're saying that you want to consume the props, and pass the props to the child untouched?
To do this, you need to destructure in a separate statement.
<DataTable
rows={tableRows}
headers={TableHeaders(t)}
render={props => {
const { rows, headers, getHeaderProps, getRowProps } = props;
// omitted
return <TableExpandedRow {...props} />
}}
I want to upload 10 images together and send a axios request to backend to do some calculations with those 10 files , after calculations there will be response as {imagename: true} or {imagename: false} receiving the response from backend I want to list those 10 images on frontend with a indication that the calculation is true or false.
This is what I tried but I'm stuck after getting response and unable to show the true or false status.
import React from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import { Grid, Row, Col } from 'react-flexbox-grid';
import axios, { post } from 'axios';
import compose from 'recompose/compose';
import { withStyles } from '#material-ui/core/styles';
import Styles from '../styles';
import Paper from '#material-ui/core/Paper';
import Button from '#material-ui/core/Button';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import { Scrollbars } from 'react-custom-scrollbars';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
class ImageUploader extends React.Component {
constructor(props) {
super(props);
this.state ={
file:null,
user_name:this.props.username,
checkboxcolor:false,
detailsResoponse:[],
responseList:[],
imageList:[],
uploadResponse:'priya',
a:[],
loaded: 0
}
this.onFormSubmit = this.onFormSubmit.bind(this)
this.handelFile = this.handelFile.bind(this)
this.fileUpload = this.fileUpload.bind(this)
}
onFormSubmit(){
this.setState({
responseList:[]
})
var files=this.state.file
for(var i in files){
this.fileUpload(files[i])
.then((response)=>{
// console.log(response.data);
})
}
}
handelFile(e) {
if(e.target.files.length == 10) {
var self=this
self.setState({
imgList:[],
file:e.target.files,
})
for(var i in e.target.files){
if(i != 'length' && i != 'item'){
if(e.target.files[i].type.split('/')[0] == 'image'){
self.state.imageList.push(e.target.files[i])
}
}
}
}
else{
alert('Please upload 10 images')
}
}
urlBlob(id,file){
var reader = new FileReader();
reader.onload = function (e) {
var image=document.getElementById(id)
image.src=e.target.result
}
reader.readAsDataURL(file);
}
fileUpload(file){
const url = 'http://abc';
const formData = new FormData();
formData.append('image',file)
const config = {
headers: {
'content-type': 'multipart/form-data',
'Access-Control-Allow-Origin':'*'
}
}
return axios.post(url,formData,config)
.then(res => {
var jsondata=JSON.stringify(res.data)
JSON.parse(jsondata, (key, value) => {
// if (value == true) {
// this.state.a.push(key)
var arrayList= this.state.responseList
arrayList.push(res.data)
this.setState({
responseList:arrayList,
// checkboxcolor:true
})
// }
});
}
)
.catch(function (error) {
alert(error)
});
}
render(){
const { classes } = this.props;
console.log(this.state.a)
console.log(this.state.imageList,"yep")
// console.log(this.state.responseList,"responseList")
return (
<div>
<Grid>
<Row>
<Col sm={12} md={12} lg={12}>
<AppBar position="static" color="inherit" className={classes.app}>
<Toolbar>
<Typography variant="title" color="inherit">
Upload Image
</Typography>
</Toolbar>
</AppBar>
</Col>
</Row>
<Row>
<Col sm={12} md={12} lg={12}>
<Paper elevation={3} style={{padding:20,height:25,marginBottom:20}}>
<input
id="fileItem"
type="file" onChange={this.handelFile}
multiple
/>
<Button color="primary" onClick={this.onFormSubmit}> Upload</Button>
</Paper>
</Col>
</Row>
<Row>
<Col sm={12} md={12} lg={12}>
<Table style={{width:'80%',position:'relative',left:'8%',border:'2px solid lightgrey',marginTop:'3%'}}>
<TableHead>
<TableRow >
<TableCell className={classes.phPadding}> Checkbox </TableCell>
<TableCell className={classes.phPadding}> Image </TableCell>
<TableCell className={classes.phPadding}> Name </TableCell>
<TableCell className={classes.phPadding}> Username</TableCell>
<TableCell style={{width:'10%'}}></TableCell>
</TableRow>
</TableHead>
</Table>
<Scrollbars style={{height: 328}}>
{this.state.imageList.map((item,key)=> (
<Table style={{width:'80%',position:'relative',left:'8%',border:'2px solid lightgrey',borderTop:'0px'}}>
<TableBody>
<TableRow key={key}>
<TableCell className={classes.phPadding}>
{this.state.checkboxcolor ?
<FormControlLabel
control={
<Checkbox
checked={this.state.checkboxcolor}
/>
}
/>
:
null
}
</TableCell>
<TableCell className={classes.phPadding}>
<img id={"image"+key} src={this.urlBlob("image"+key,item)} height="90" width="90" />
</TableCell>
<TableCell className={classes.phPadding}>{item.name}</TableCell>
<TableCell className={classes.phPadding}>{/* {this.state.user_name} */}user_name</TableCell>
<TableCell>
</TableCell>
</TableRow>
</TableBody>
</Table>
))}
</Scrollbars>
</Col>
</Row>
</Grid>
</div>
)
}
}
export default compose(withStyles(Styles))(ImageUploader);
console.log(res.data) response
EDIT: To fix below issue you need to add event.persist() under handleFile function.
Uncaught TypeError: Cannot read property 'files' of null
I updated all the code using ES6.
I noticed some bad practices in your code and corrected them
The way you push elements to state array is not right instead use
previous state to play with array in react state.
Stop using var
instead use let and const
Stop assigning this to self instead use arrow
functions so that you no need to do manual binding and no need to depend on local variable i.e., self
I have corrected your code. This code will show the image responses as you needed
import React from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import { Grid, Row, Col } from 'react-flexbox-grid';
import axios, { post } from 'axios';
import compose from 'recompose/compose';
import { withStyles } from '#material-ui/core/styles';
import Styles from '../styles';
import Paper from '#material-ui/core/Paper';
import Button from '#material-ui/core/Button';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import { Scrollbars } from 'react-custom-scrollbars';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
class ImageUploader extends React.Component {
constructor(props) {
super(props);
this.state ={
file:null,
user_name:this.props.username,
detailsResoponse:[],
responseList:[],
imageList:[],
uploadResponse:'priya',
a:[],
loaded: 0
}
}
onFormSubmit = () => {
this.setState({
responseList:[]
})
let files = this.state.file;
for(var i in files){
this.fileUpload(files[i]);
}
}
handelFile = e => {
e.persist();
if(e.target.files.length == 10) {
this.setState({
imgList:[],
file:e.target.files,
})
for(let i=0; i < e.target.files.length; i++){
if(e.target.files[i].type.split('/')[0] == 'image'){
this.setState(prevState => ({
imageList: [...prevState.imageList, e.target.files[i]]
}));
}
}
}
else{
alert('Please upload 10 images')
}
}
urlBlob = (id,file) => {
let reader = new FileReader();
reader.onload = e => {
let image = document.getElementById(id);
image.src = e.target.result;
}
reader.readAsDataURL(file);
}
fileUpload = file => {
const url = 'http://172.16.92.21:9999';
const formData = new FormData();
formData.append('image',file)
formData.append('uname','150180')
const config = {
headers: {
'content-type': 'multipart/form-data',
'Access-Control-Allow-Origin':'*'
}
}
axios.post(url, formData, config)
.then(res => {
this.setState(prevState => ({
responseList: [...prevState.responseList, res.data]
}));
});
.catch(error => {
alert(error)
});
}
render(){
const { classes } = this.props;
const { responseList } = this.props;
console.log(this.state.a)
console.log(this.state.imageList,"yep")
// console.log(this.state.responseList,"responseList")
const imagesResponse = responseList && responseList.map((image, index) => {
return <li className="list-group-item">{image}</li>
});
return (
<div>
<Grid>
<Row>
<Col>
<ul className="list-group">
{imagesResponse}
</ul>
</Col>
</Row>
<Row>
<Col sm={12} md={12} lg={12}>
<AppBar position="static" color="inherit" className={classes.app}>
<Toolbar>
<Typography variant="title" color="inherit">
Upload Image For Surveillance
</Typography>
</Toolbar>
</AppBar>
</Col>
</Row>
<Row>
<Col sm={12} md={12} lg={12}>
<Paper elevation={3} style={{padding:20,height:25,marginBottom:20}}>
<input
id="fileItem"
type="file" onChange={this.handelFile}
multiple
/>
<Button color="primary" onClick={this.onFormSubmit}> Upload</Button>
</Paper>
</Col>
</Row>
<Row>
<Col sm={12} md={12} lg={12}>
<Table style={{width:'80%',position:'relative',left:'8%',border:'2px solid lightgrey',marginTop:'3%'}}>
<TableHead>
<TableRow >
<TableCell className={classes.phPadding}> Checkbox </TableCell>
<TableCell className={classes.phPadding}> Image </TableCell>
<TableCell className={classes.phPadding}> Name </TableCell>
<TableCell className={classes.phPadding}> Username</TableCell>
<TableCell style={{width:'10%'}}></TableCell>
</TableRow>
</TableHead>
</Table>
<Scrollbars style={{height: 328}}>
{this.state.imageList && this.state.imageList.map((item,key)=> (
<Table style={{width:'80%',position:'relative',left:'8%',border:'2px solid lightgrey',borderTop:'0px'}}>
<TableBody>
<TableRow key={key}>
<TableCell className={classes.phPadding}>
{responseList ? responseList.map((image, index) => {
return (<FormControlLabel key={index}
control={
<Checkbox
checked={item.name == image.name && image.flag ? true : false }
/>
}
/>)
}): <FormControlLabel
control={
<Checkbox
checked={false}
/>
}
/>
}
</TableCell>
<TableCell className={classes.phPadding}>
<img id={"image"+key} src={this.urlBlob("image"+key,item)} height="90" width="90" />
</TableCell>
<TableCell className={classes.phPadding}>{item.name}</TableCell>
<TableCell className={classes.phPadding}>{/* {this.state.user_name} */}user_name</TableCell>
<TableCell>
</TableCell>
</TableRow>
</TableBody>
</Table>
))}
</Scrollbars>
</Col>
</Row>
</Grid>
</div>
)
}
}
export default compose(withStyles(Styles))(ImageUploader);
Please test from your side and let me know