I have two components. A parent component which englobes table of items and an edit component which is opend when only one item is selected to be modified. this is the parent component:
import * as React from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Title from './Title';
import Grid from '@mui/material/Grid';
import Paper from '@mui/material/Paper';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Container from '@mui/material/Container';
import { useState, useEffect } from "react";
import ReportDataService from "../services/report";
import FormDialogAdd from "./add-report";
import DeleteDialog from "./delete-report";
import FormDialogEdit from "./edit-report";
const ReportsList = props => {
const [reports, setReports] = useState([]);
// console.log("salut",reports)
const retrieveReports = () => {
ReportDataService.getAll()
.then(response => {
// console.log(response.data);
setReports(response.data.reports);
})
.catch(e => {
console.log(e);
});
};
// update dom after changes were made
useEffect(() => {
retrieveReports();
}, []);
return (
<Box
component="main"
sx={{
backgroundColor: (theme) =>
theme.palette.mode === 'light'
? theme.palette.grey[100]
: theme.palette.grey[900],
flexGrow: 1,
height: '100vh',
overflow: 'auto',
}}
>
<Toolbar />
<Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
<Grid container spacing={3}>
{/* Recent Orders */}
<Grid item xs={12}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column' }}>
<React.Fragment>
<Title>Reports</Title>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>name</TableCell>
<TableCell>ecu</TableCell>
<TableCell>category</TableCell>
<TableCell>lastModified</TableCell>
<TableCell>comment</TableCell>
<TableCell>reviewed</TableCell>
</TableRow>
</TableHead>
<TableBody>
{reports.map((report, index) => (
<TableRow key={index}>
<TableCell required>{report.name}</TableCell>
<TableCell>{report.ecu}</TableCell>
<TableCell>{report.category}</TableCell>
<TableCell>{report.lastModified.slice(0,10)}</TableCell>
<TableCell>{report.comment}</TableCell>
<TableCell>{report.reviewd ? "True" : "False"}</TableCell>
<Box sx={{ display: 'flex' }}>
<FormDialogEdit reportId={report._id}/>
<DeleteDialog reportId={report._id} />
</Box>
</TableRow>
))}
</TableBody>
</Table>
</React.Fragment>
</Paper>
<FormDialogAdd/>
</Grid>
</Grid>
</Container>
</Box>
);
};
export default ReportsList;
and this code is for the child component for edit:
import * as React from 'react';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import ListItemButton from '@mui/material/ListItemButton';
import FormControlLabel from '@mui/material/FormControlLabel';
import Switch from '@mui/material/Switch';
import ListItemText from '@mui/material/ListItemText';
import DialogTitle from '@mui/material/DialogTitle';
import Fab from '@mui/material/Fab';
import EditIcon from '@mui/icons-material/Edit';
import ReportDataService from "../services/report";
import Box from '@mui/material/Box';
import { useState, useEffect } from "react";
export default function FormDialogEdit(props) {
const [open, setOpen] = React.useState(false);
const handleClose = () => {
setOpen(false);
};
const getSingleReport = (reportId) => {
setOpen(true);
// console.log(reportId)
ReportDataService.get(reportId)
.then(response => {
// console.log("data",response.data);
setReport(response.data);
})
.catch(e => {
console.log(e);
});
};
let initialReportState = ""
const [report, setReport] = useState(initialReportState);
// begins always false=> not convincing param=> should be updated like reviewd
const [manualTest, setManualTest] = React.useState(false);
const handleChangeTestManual = (event) =>{
setManualTest(event.target.checked)
}
const [inputs, setInputs] = useState({});
console.log(inputs);
const handleChange = e => setInputs(prevState => ({ ...prevState, [e.target.name]: e.target.value }));
const handleChangeReviewed= e => setInputs(prevState => ({ ...prevState, [e.target.name]: e.target.checked }));
// console.log("hi",inputs)
const saveReport = () => {
ReportDataService.updateReport(inputs)
.then(response => {
// console.log(response.data);
})
.catch(e => {
console.log(e);
});
};
useEffect(() => {
setInputs(report)
}, [report]);
return (
<div>
<Fab size="small" sx={{ m: 1}} color="primary" aria-label="edit" onClick={() => getSingleReport(props.reportId)}>
<EditIcon />
</Fab>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Edit report</DialogTitle>
<DialogContent>
<DialogContentText>
You can see here all informations about a report and modify parameters
</DialogContentText>
<Box sx={{ border: 1, borderColor: 'grey.500', borderRadius: 2, marginTop:2}}>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Name"
name="name"
type="text"
value={inputs.name}
onChange={handleChange}
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Ecu"
name="ecu"
value={inputs.ecu}
onChange={handleChange}
type="text"
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Category"
name="category"
value={inputs.category}
onChange={handleChange}
type="text"
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Comment"
name="comment"
value={inputs.comment}
onChange={handleChange}
type="text"
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<FormControlLabel
control={
<Switch
checked= {manualTest}
onChange={handleChangeTestManual}
/>
}
label="Manual test" />
</ListItemButton>
<ListItemButton>
<FormControlLabel
control={
<Switch
checked= {inputs.reviewd}
name="reviewd"
onChange={handleChangeReviewed}
/>
} label="Reviewed" />
</ListItemButton>
</Box>
<Box sx={{ border: 1, borderColor: 'grey.500', borderRadius: 2, marginTop:2}}>
<ListItemButton>
<ListItemText primary="Last Modified by" secondary={report.lastModifiedBy} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Last Modified" secondary={report.lastModified} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Rating" secondary={report.rating} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Error injection" secondary={report.errorInjection} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Simulation" secondary={report.simulation} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Test cases" secondary={report.testCases} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Last run" secondary={report.lastRun} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="File" secondary={report.file} />
</ListItemButton>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={() =>{
saveReport();
handleClose();
}}>
Update</Button>
</DialogActions>
</Dialog>
</div>
);
}
I want to be able to update the parent component when clicking on the update button in the child component. In other world I want the parent component to refresh and modify changes directly. The solution from what i saw is with useEffect but i didn`t know how to use it. So can anyone help? How to notify the parent that a changment has been made so that the table should be updated as soon as the update button in the child is clicked?
CodePudding user response:
add a new prop to the child component which passes setReport
, this can then be called within the child component and the state will update within the parent making it refresh
<FormDialogEdit reportId={report._id} setReport={setReport}/>
CodePudding user response:
Add a props into your child component
like this props.func('updated');
import * as React from 'react';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import ListItemButton from '@mui/material/ListItemButton';
import FormControlLabel from '@mui/material/FormControlLabel';
import Switch from '@mui/material/Switch';
import ListItemText from '@mui/material/ListItemText';
import DialogTitle from '@mui/material/DialogTitle';
import Fab from '@mui/material/Fab';
import EditIcon from '@mui/icons-material/Edit';
import ReportDataService from "../services/report";
import Box from '@mui/material/Box';
import { useState, useEffect } from "react";
export default function FormDialogEdit(props) {
props.func('updated');
const [open, setOpen] = React.useState(false);
const handleClose = () => {
setOpen(false);
};
const getSingleReport = (reportId) => {
setOpen(true);
// console.log(reportId)
ReportDataService.get(reportId)
.then(response => {
// console.log("data",response.data);
setReport(response.data);
})
.catch(e => {
console.log(e);
});
};
let initialReportState = ""
const [report, setReport] = useState(initialReportState);
// begins always false=> not convincing param=> should be updated like reviewd
const [manualTest, setManualTest] = React.useState(false);
const handleChangeTestManual = (event) =>{
setManualTest(event.target.checked)
}
const [inputs, setInputs] = useState({});
console.log(inputs);
const handleChange = e => setInputs(prevState => ({ ...prevState, [e.target.name]: e.target.value }));
const handleChangeReviewed= e => setInputs(prevState => ({ ...prevState, [e.target.name]: e.target.checked }));
// console.log("hi",inputs)
const saveReport = () => {
ReportDataService.updateReport(inputs)
.then(response => {
// console.log(response.data);
})
.catch(e => {
console.log(e);
});
};
useEffect(() => {
setInputs(report)
}, [report]);
return (
<div>
<Fab size="small" sx={{ m: 1}} color="primary" aria-label="edit" onClick={() => getSingleReport(props.reportId)}>
<EditIcon />
</Fab>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Edit report</DialogTitle>
<DialogContent>
<DialogContentText>
You can see here all informations about a report and modify parameters
</DialogContentText>
<Box sx={{ border: 1, borderColor: 'grey.500', borderRadius: 2, marginTop:2}}>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Name"
name="name"
type="text"
value={inputs.name}
onChange={handleChange}
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Ecu"
name="ecu"
value={inputs.ecu}
onChange={handleChange}
type="text"
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Category"
name="category"
value={inputs.category}
onChange={handleChange}
type="text"
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<TextField
autoFocus
margin="dense"
id="name"
label="Comment"
name="comment"
value={inputs.comment}
onChange={handleChange}
type="text"
fullWidth
variant="standard"
/>
</ListItemButton>
<ListItemButton>
<FormControlLabel
control={
<Switch
checked= {manualTest}
onChange={handleChangeTestManual}
/>
}
label="Manual test" />
</ListItemButton>
<ListItemButton>
<FormControlLabel
control={
<Switch
checked= {inputs.reviewd}
name="reviewd"
onChange={handleChangeReviewed}
/>
} label="Reviewed" />
</ListItemButton>
</Box>
<Box sx={{ border: 1, borderColor: 'grey.500', borderRadius: 2, marginTop:2}}>
<ListItemButton>
<ListItemText primary="Last Modified by" secondary={report.lastModifiedBy} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Last Modified" secondary={report.lastModified} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Rating" secondary={report.rating} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Error injection" secondary={report.errorInjection} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Simulation" secondary={report.simulation} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Test cases" secondary={report.testCases} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="Last run" secondary={report.lastRun} />
</ListItemButton>
<ListItemButton>
<ListItemText primary="File" secondary={report.file} />
</ListItemButton>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={() =>{
saveReport();
handleClose();
}}>
Update</Button>
</DialogActions>
</Dialog>
</div>
);
}
**And in Parent component ** use that props like this
import Container from '@mui/material/Container';
import { useState, useEffect } from "react";
import ReportDataService from "../services/report";
import FormDialogAdd from "./add-report";
import DeleteDialog from "./delete-report";
import FormDialogEdit from "./edit-report";
const ReportsList = props => {
const [reports, setReports] = useState([]);
// console.log("salut",reports)
const retrieveReports = () => {
ReportDataService.getAll()
.then(response => {
// console.log(response.data);
setReports(response.data.reports);
})
.catch(e => {
console.log(e);
});
};
// update dom after changes were made
useEffect(() => {
retrieveReports();
}, []);
return (
<Box
component="main"
sx={{
backgroundColor: (theme) =>
theme.palette.mode === 'light'
? theme.palette.grey[100]
: theme.palette.grey[900],
flexGrow: 1,
height: '100vh',
overflow: 'auto',
}}
>
<Toolbar />
<Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
<Grid container spacing={3}>
{/* Recent Orders */}
<Grid item xs={12}>
<Paper sx={{ p: 2, display: 'flex', flexDirection: 'column' }}>
<React.Fragment>
<Title>Reports</Title>
<Table size="small">
<TableHead>
<TableRow>
<TableCell>name</TableCell>
<TableCell>ecu</TableCell>
<TableCell>category</TableCell>
<TableCell>lastModified</TableCell>
<TableCell>comment</TableCell>
<TableCell>reviewed</TableCell>
</TableRow>
</TableHead>
<TableBody>
{reports.map((report, index) => (
<TableRow key={index}>
<TableCell required>{report.name}</TableCell>
<TableCell>{report.ecu}</TableCell>
<TableCell>{report.category}</TableCell>
<TableCell>{report.lastModified.slice(0,10)}</TableCell>
<TableCell>{report.comment}</TableCell>
<TableCell>{report.reviewd ? "True" : "False"}</TableCell>
<Box sx={{ display: 'flex' }}>
<FormDialogEdit reportId={report._id} func={retrieveReports}/>
<DeleteDialog reportId={report._id} />
</Box>
</TableRow>
))}
</TableBody>
</Table>
</React.Fragment>
</Paper>
<FormDialogAdd/>
</Grid>
</Grid>
</Container>
</Box>
);
};
export default ReportsList;