how to update parent component when changing child component? - javascript

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?

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;

add a new prop to the child component which passes retrieveReports , this can then be called within the child component and the state will update within the parent making it refresh
<FormDialogEdit reportId={report._id} retrieveReports={retrieveReports}/>
Called within child with : props.retrieveReports()

Related

Get value from few Select in Material-UI

I have two MUI Select components on my page. I'm trying to set values depends on id of Select. I've checked (id === "breed-select") in console and (at first) it's true, but immediately after that it become false, and i cant understand why. Where i made a mistake? May be there is a better way to set values of two Select components? CodeSandbox
import React from 'react';
import './AddCatPopup.css';
import {Box, Button, FormControl, InputLabel, MenuItem, Select, TextField} from '#mui/material';
import {theme} from '../../theme';
import {ThemeProvider} from '#mui/material/styles';
function AddCatPopup({ breeds, isOpen, onClose, onAddCat }) {
const breedsName = breeds.map(item => item.nameBreed);
const colorsArray = [
'black',
'white',
'grey',
'red',
'multicolor'
];
const [name, setName] = React.useState('');
const [price, setPrice] = React.useState(0);
const [color, setColor] = React.useState('');
const [age, setAge] = React.useState(0);
const [breed, setBreed] = React.useState('');
function handleChange(event) {
const {
target: { value, id }
} = event;
id === "breed-select" ? setBreed(value) : setColor(value);
}
function handleSubmit(e) {
e.preventDefault();
}
return(
<section className={`popup ${isOpen && 'popup_opened'}`}>
<div className={'popup__container'}>
<button type="button" className={'popup__close-btn'} onClick={onClose}></button>
<p className={'popup__title'}>Enter info about cat</p>
<TextField sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Name"
required />
<TextField sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Price"
required />
<FormControl sx={{ mt: 1, mb: 1 }}
variant="standard"
required>
<InputLabel id="breed-label">Breed</InputLabel>
<Select
labelId="filter-breed"
id="breed-select"
label="Breed"
value={breed}
onChange={handleChange}
>
{breedsName.map((item) => (
<MenuItem
key={item}
value={item}
id="breed-select"
>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl sx={{ mt: 1, mb: 1 }}
variant="standard"
required>
<InputLabel id="color-label">Color</InputLabel>
<Select
labelId="filter-color"
id="color-select"
label="Color"
value={color}
onChange={handleChange}
>
{colorsArray.map((item) => (
<MenuItem
key={item}
value={item}
id="color-select"
>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<TextField sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Age"
required />
<ThemeProvider theme={theme}>
<Button sx={{ mt: 1, mb: 1 }}
variant="contained"
color={'secondary'}
onClick={handleSubmit}>
Add
</Button>
</ThemeProvider>
</div>
</section>
);
}
export default AddCatPopup;
The main problem was that you doesn't get id and value correctly. I understand why you wrote this code, but unfortunately the event which come into handleChange is MouseEvent | PointerEvent so you could not get the correct id and value. The reason why you could choose color in this part id === "breed-select" ? setBreed(value) : setColor(value); you always got id = undefined so the setColor is fired always. You should use second argument of handleChange function. You can copypaste below code to see how does it work now
import React from "react";
import "./AddCatPopup.css";
import {
Button,
FormControl,
InputLabel,
MenuItem,
Select,
TextField
} from "#mui/material";
import { theme } from "./theme";
import { ThemeProvider } from "#mui/material/styles";
function AddCatPopup({ breeds, isOpen, onClose, onAddCat }) {
const breedsName = breeds.map((item) => item.nameBreed);
const colorsArray = ["black", "white", "grey", "red", "multicolor"];
const [name, setName] = React.useState("");
const [price, setPrice] = React.useState(0);
const [age, setAge] = React.useState(0);
const [color, setColor] = React.useState("");
const [breed, setBreed] = React.useState("");
function handleChange(event, obj) {
const target = object.props;
const id = target.id;
const value = target.value;
/breed-option/.test(id) ? setBreed(value) : setColor(value);
}
function handleSubmit(e) {
e.preventDefault();
}
return (
<section className={`popup ${isOpen && "popup_opened"}`}>
<div className={"popup__container"}>
<button
type="button"
className={"popup__close-btn"}
onClick={onClose}
></button>
<p className={"popup__title"}>Enter info about cat</p>
<TextField
sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Name"
required
/>
<TextField
sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Price"
required
/>
<FormControl sx={{ mt: 1, mb: 1 }} variant="standard" required>
<InputLabel id="breed-label">Breed</InputLabel>
<Select
labelId="filter-breed"
id="breed-select"
label="Breed"
value={breed}
onChange={handleChange}
>
{breedsName.map((item, index) => (
<MenuItem key={item} value={item} id={'breed-option-' + index}>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<FormControl sx={{ mt: 1, mb: 1 }} variant="standard" required>
<InputLabel id="color-label">Color</InputLabel>
<Select
labelId="filter-color"
id="color-select"
label="Color"
value={color}
onChange={handleChange}
>
{colorsArray.map((item, index) => (
<MenuItem key={item} value={item} id={"color-option-" + index}>
{item}
</MenuItem>
))}
</Select>
</FormControl>
<TextField
sx={{ mt: 1, mb: 1 }}
id="standard-required"
variant="standard"
label="Age"
required
/>
<ThemeProvider theme={theme}>
<Button
sx={{ mt: 1, mb: 1 }}
variant="contained"
color={"secondary"}
onClick={handleSubmit}
>
Add
</Button>
</ThemeProvider>
</div>
</section>
);
}
export default AddCatPopup;

React + Formik + redux: An unhandled error was caught from submitForm() TypeError: Object(...) is not a function

I'am struggling with this error, I'm using Formik + redux to handle React Form, so I had this following warning when I submit button:
react_devtools_backend.js:2560 Warning: An unhandled error was caught from submitForm() TypeError: Object(...) is not a function
at onSubmit (LoginContainer.js:72)
at Formik.tsx:849
at Formik.tsx:1200
at Formik.tsx:756
According to the warning, the error is on line 72 : where is wrote :
dispatch(login(payload.email, payload.password));
Even if I deleted keyword dispatch , I still get error.
Here is my LoginContainer funtional component:
import React from "react";
import { Link as RouterLink } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import {
Grid,
Typography,
TextField,
Container,
Link,
Box,
Button,
Checkbox,
InputLabel,
FormGroup,
FormControlLabel,
IconButton,
OutlinedInput,
FormControl,
FormHelperText,
InputAdornment,
} from "#material-ui/core";
import Visibility from "#material-ui/icons/Visibility";
import VisibilityOff from "#material-ui/icons/VisibilityOff";
import * as Yup from "yup";
import { Formik } from "formik";
import AuthLayout from "../../../components/AuthLayout";
import { FORGOTPASSWORD } from "../../../navigation/CONSTANT";
import login from "../../../services/AuthService";
//styles
//Login component
export function LoginContainer() {
const [rootValues, setRootValues] = React.useState({
showPassword: true,
});
// ======= Password function ===========/
const handleClickShowPassword = () => {
setRootValues({
showPassword: !rootValues.showPassword,
});
};
const handleMouseDownPassword = (event) => {
event.preventDefault();
};
//=================== end ===============/
const dispatch = useDispatch();
const initialValues = {
email: "example#rilc.com",
password: "motdepasse",
};
const validationSchema = Yup.object().shape({
email: Yup.string()
.email("L'adresse mail doit être valide")
.max(50)
.required("L'adresse mail est obligatoire"),
password: Yup.string().max(50).required("Le mot de passe est obligatoire"),
});
function onSubmit(values, { setSubmitting }) {
/*alert(JSON.stringify(values, null, 2));*/
const payload = {
email: values.email,
password: values.password,
};
dispatch(login(payload.email, payload.password));
}
return (
<AuthLayout>
<Box
sx={{
backgroundColor: "background.default",
display: "flex",
flexDirection: "column",
height: "100%",
justifyContent: "center",
}}
>
<Container maxWidth="sm">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{({
errors,
handleBlur,
handleChange,
handleSubmit,
isSubmitting,
touched,
values,
}) => (
<form onSubmit={handleSubmit}>
<Box sx={{ mb: 3, ml: 10 }}>
<Typography color="textPrimary" variant="h3" textAlign="left">
Connexion
</Typography>
</Box>
<Grid container spacing={3}></Grid>
<Box
sx={{
pb: 1,
pt: 4,
}}
></Box>
<Box
sx={{
ml: 10,
}}
>
<TextField
error={Boolean(touched.email && errors.email)}
fullWidth
helperText={touched.email && errors.email}
label="Email"
margin="normal"
name="email"
onBlur={handleBlur}
onChange={handleChange}
type="email"
value={values.email}
variant="outlined"
/>
<FormControl
sx={{ mt: 3 }}
variant="outlined"
fullWidth
onChange={handleChange}
onBlur={handleBlur}
error={Boolean(touched.password && errors.password)}
>
<InputLabel htmlFor="outlined-adornment-password">
Password
</InputLabel>
<OutlinedInput
id="outlined-adornment-password"
type={rootValues.showPassword ? "text" : "password"}
value={values.password}
name="password"
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{rootValues.showPassword ? (
<Visibility />
) : (
<VisibilityOff />
)}
</IconButton>
</InputAdornment>
}
label="Password"
/>
<FormHelperText id="component-error-text">
{touched.password && errors.password}
</FormHelperText>
</FormControl>
<Box
sx={{
display: "grid",
columnGap: 2,
rowGap: 1,
mt: 3,
gridTemplateColumns: "repeat(2, 0.5fr)",
}}
>
<Box>
<FormGroup>
<FormControlLabel
control={<Checkbox defaultChecked />}
label="Se souvenir de moi"
/>
</FormGroup>
</Box>
<Box sx={{ mt: 1, textAlign: "right" }}>
<Link component={RouterLink} to={FORGOTPASSWORD}>
Mot de passe oublié?
</Link>
</Box>
</Box>
<Box sx={{ py: 2 }}>
<Button
color="primary"
disabled={isSubmitting}
fullWidth
size="large"
type="submit"
variant="contained"
>
Se connecter
</Button>
</Box>
</Box>
</form>
)}
</Formik>
</Container>
</Box>
</AuthLayout>
);
}
Thanks for you help.

Link tag changes my history location but then changes back to original home page React.js

So I have been having this issue with a project I've been working on for 2 days now and I don't know why. I have used React-router-dom before for my webapps and I have never encountered this issue in all the months I've used React.js I basically have my Switch component, BrowserRouter wrapped around App.js, and everything, but every time I click the link to my new route "/register", the URL would change for a few 2 seconds and then change back to my login homepage. this happens without me doing anything or clicking anything. I've tried changing link tag attribute from to="/register" to href="/register" but that didn't work. It's infuriating, Here's my code:
Index.js
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {BrowserRouter} from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
App.js
import React,{Component} from 'react';
import { Router, Switch, Route, withRouter, Link} from 'react-router-dom'
import HomePage from "./components/HomePage";
import Register from "./components/Register"
import Dashboard from "./components/Dashboard"
// import Link from '#material-ui/core/Link';
// import { background } from "./images/7f76e8e7692375107e5998013155af0d.jpg";
// import { TravelerEffect, MosaicGroundEffect, OceanEffect,
// RainEffect, SeaWaveEffect, SnowFallEffect, SnowFallSlowEffect,
// SpacingEffect, CloudWaveEffect
// } from 'react-background-animation'
class App extends Component {
state = {
user: {
email: "",
username: "",
is_active: "",
first_name: "",
last_name: "",
bio: "",
age: "",
birth_place: "",
school: "",
occupation: "",
what_are_you_seeking_on_site: "",
profile_pic: null,
loginErrors: "",
},
token: "",
}
handleResponse (resp) {
console.log(resp.user);
if (resp.user) {
localStorage.setItem('token', resp.token)
this.setState({
user: resp.user,
token: resp.token
}, () => {
this.props.history.push("/dashboard")
})
}
else {
alert(resp.error)
}
}
componentDidMount(){
if (localStorage.getItem("token")) {
fetch('http://localhost:8000/current_user/', {
headers: {
Authorization: `Bearer ${localStorage.token}`
}
})
.then(r => r.json())
.then(this.handleResp)
}
}
handleRegister(newUser){
fetch( "http://127.0.0.1:8000/rest-auth/registration/", {
method: "POST",
headers: {
'content-type': "application/json"
},
body: JSON.stringify(newUser)
})
.then(res => res.json())
.then(this.handleResponse)
}
handleLogin(returningUser){
fetch('http://127.0.0.1:8000/rest-auth/login/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(returningUser)
})
.then(res => res.json())
.then(this.handleResponse)
}
renderRegisterForm = (routerProps) => {
if (routerProps.location.pathname === "/register") {
// debugger
return <Register formName="Register Form"
handleSubmit={this.handleRegister}
/>
}else if(routerProps.location.pathname === "/") {
return <HomePage formName="Log into Account"
handleSubmit={this.handleLogin}
/>
}
}
render() {
return (
<div>
{/* <Link to="/register">Sign Up</Link> */}
<Switch>
<Route exact path="/" render={this.renderRegisterForm} />
<Route exact path="/register" render={this.renderRegisterForm} />
<Route path="/dashboard" exact component={Dashboard} />
<Route render={ () => <p>Page not Found</p> } />
</Switch>
{/* <Link href="/register"
// onClick={this.handleRegisterLinkPage}
variant="body1">
{"Don't have an account? Sign Up"}
</Link> */}
</div>
);
}
}
export default withRouter(App);
my HomePage.jsx (which is basically my login page)
import React from 'react';
import {Redirect} from "react-router-dom"
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Link from '#material-ui/core/Link';
import Paper from '#material-ui/core/Paper';
import Box from '#material-ui/core/Box';
import Grid from '#material-ui/core/Grid';
// import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import Typography from '#material-ui/core/Typography';
import { withStyles } from '#material-ui/core/styles';
const useStyles = theme => ({
root: {
height: '100vh',
},
image: {
backgroundImage: 'url(https://source.unsplash.com/random)',
backgroundRepeat: 'no-repeat',
backgroundColor:
theme.palette.type === 'light' ? theme.palette.grey[50] : theme.palette.grey[900],
backgroundSize: 'cover',
backgroundPosition: 'center',
},
paper: {
margin: theme.spacing(8, 4),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
});
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
class HomePage extends React.Component {
// handleRegisterLinkPage = (event) => {
// event.preventDefault()
// return<Redirect to={"/register"}/>
// // debugger
// }
render(){
const {classes} = this.props
return (
<Grid container component="main" className={classes.root}>
<CssBaseline />
<Grid item xs={false} sm={4} md={7} className={classes.image} />
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
<div className={classes.paper}>
<Avatar className={classes.avatar}>
{/* <LockOutlinedIcon /> */}
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
{/* <Link href="#" variant="body2">
Forgot password?
</Link> */}
</Grid>
<Grid item>
<Link href="/register"
// onClick={this.handleRegisterLinkPage}
variant="body1">
<Button> Don't have an account? Sign Up</Button>
</Link>{' '}
</Grid>
</Grid>
<Box mt={5}>
<Copyright />
</Box>
</form>
</div>
</Grid>
</Grid>
);
}
}
export default withStyles(useStyles)(HomePage)
And Lastly My register page, which I feel I shouldn't have to show, but here it is anyway
import React, { useState, useEffect } from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Link from '#material-ui/core/Link';
import Grid from '#material-ui/core/Grid';
import Box from '#material-ui/core/Box';
import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import Typography from '#material-ui/core/Typography';
import { makeStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
import TextareaAutosize from '#material-ui/core/TextareaAutosize';
import { MuiPickersUtilsProvider, KeyboardDatePicker } from '#material-ui/pickers';
import FormControl from '#material-ui/core/FormControl';
import FormLabel from '#material-ui/core/FormLabel';
import Radio from '#material-ui/core/Radio';
import RadioGroup from '#material-ui/core/RadioGroup';
import DateFnsUtils from '#date-io/date-fns';
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(3),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
export default function Register() {
const classes = useStyles();
const [email, setEmail] = useState(" ")
const [password, setPassword] = useState(" ")
const [confirmPassword, setConfirmPassword] = useState(" ")
const [username, setUsername] = useState(" ")
const [birthPlace, setBirthPlace] = useState(" ")
const [bio, setBio] = useState(" ")
const [school, setSchool] = useState(" ")
const [firstName, setFirstName] = useState(" ")
const [lastName, setLastName] = useState(" ")
const [occupation, setOccupation] = useState(" ")
const [what_are_you_seeking_on_site, setWhat_are_you_seeking_on_site] = useState("Friendship")
const [age, setAge] = useState(new Date('2014-08-18T21:11:54'));
const [errors, setErrors] = useState(" ")
// const [selectedDate, setSelectedDate] =
// const [value, setValue] = React.useState('Friendship');
useEffect(() => {
if (localStorage.getItem('token') !== null) {
window.location.replace('http://localhost:3000/dashboard');
} else {
window.location.replace('http://localhost:3000/')
}
}, []);
const handleSubmit = e => {
e.preventDefault();
const user = {
email: email,
username: username,
birthPlace: birthPlace,
bio: bio,
school: school,
age: age,
password: password,
confirmPassword: confirmPassword,
firstName: firstName,
lastName: lastName,
occupation: occupation,
what_are_you_seeking_on_site: what_are_you_seeking_on_site,
};
fetch('http://127.0.0.1:8000/rest-auth/registration/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
.then(res => res.json())
.then(data => {
if (data.key) {
localStorage.clear();
localStorage.setItem('token', data.key);
window.location.replace('http://localhost:3000/dashboard');
} else {
setEmail('');
setPassword('');
setConfirmPassword('');
localStorage.clear();
setErrors(true);
}
});
};
const handleChange = (event) => {
setWhat_are_you_seeking_on_site(event.target.value);
};
const handleDateChange = (date) => {
setAge(date);
};
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign up
</Typography>
<form className={classes.form} onSubmit={handleSubmit} noValidate>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Grid item xs={12} sm={6}>
<TextField
autoComplete="username"
name="Username"
variant="outlined"
required
fullWidth
id="Username"
label="Username"
autoFocus
value={e => setUsername(e.target.value)}
/>
</Grid>
<TextField
autoComplete="fname"
name="firstName"
variant="outlined"
required
fullWidth
id="firstName"
label="First Name"
autoFocus
value={e => setFirstName(e.target.value)}
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
variant="outlined"
required
fullWidth
id="lastName"
label="Last Name"
name="lastName"
value={e => setLastName(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
id="email"
label="Email Address"
name="email"
value={e => setEmail(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
value={e => setPassword(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="Confirm password"
label="Confirm Password"
type="password2"
id="password2"
value={e => setConfirmPassword(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextareaAutosize
aria-label="minimum height"
fullWidth
label="Bio"
rowsMin={3}
placeholder="Minimum 3 rows"
value={e => setBio(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="Birth Place"
label="Where were you born"
id="birthPlace"
value={e => setBirthPlace(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="School"
label="School"
id="School"
value={e => setSchool(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="Occupation"
label="Occupation"
id="Occupation"
value={e => setOccupation(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<FormControl component="fieldset">
<FormLabel component="legend">What are you here for</FormLabel>
<RadioGroup aria-label="what_are_you_seeking_on_site" name="what_are_you_seeking_on_site" value={what_are_you_seeking_on_site} onChange={handleChange}>
<FormControlLabel value="Dating" control={<Radio />} label="Dating" />
<FormControlLabel value="Friendship" control={<Radio />} label="Friendship" />
<FormControlLabel value="Networking" control={<Radio />} label="Networking" />
<FormControlLabel value="Business" control={<Radio />} label="Business" />
</RadioGroup>
</FormControl>
</Grid>
<Grid item xs={12}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<KeyboardDatePicker
margin="normal"
id="date-picker-dialog"
label="Date picker dialog"
format="MM/dd/yyyy"
// value={selectedDate}
onChange={handleDateChange}
KeyboardButtonProps={{
'aria-label': 'change date',
}}
value={e => setAge(e.target.value)}
/>
</MuiPickersUtilsProvider>
</Grid>
<Grid item xs={12}>
<FormControlLabel
control={<Checkbox value="allowExtraEmails" color="primary" />}
label="I want to receive inspiration, marketing promotions and updates via email."
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign Up
</Button>
<Grid container justify="flex-end">
<Grid item>
<Link href="/" variant="body2">
Already have an account? Sign in
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={5}>
<Copyright />
</Box>
</Container>
);
}
Please Help me
When your Register component mounts you've an useEffect hook that runs and either bounces the user to "/dashboard" or "/".
useEffect(() => {
if (localStorage.getItem('token') !== null) {
window.location.replace('http://localhost:3000/dashboard');
} else {
window.location.replace('http://localhost:3000/')
}
}, []);
If the token exists and isn't null then bouncing a user to the dashboard path is probably acceptable. You may not want to bounce users to the homepage when they are trying to register so you can likely remove the else branch entirely.
useEffect(() => {
if (localStorage.getItem('token') !== null) {
window.location.replace('http://localhost:3000/dashboard');
}
}, []);

How to edit items inside en Array Input in React admin?

I have an object that contains objects and each of them has an array of items, I want to attach to each of them an edit button for viewing and deleting In React-admin, but something in my code fails and every time I press the buttons everything gets stuck, you can see in the pictures here:
Thanks!
when I press this buttons the web get stuck:
The buttons in the code:
The Edit part:
The data:
import React from "react";
import {
List,
Datagrid,
TextField,
EmailField,
EditButton,
DeleteButton,
Filter,
TextInput,
ReferenceInput,
SelectInput,
BulkDeleteWithConfirmButton,
DeleteWithConfirmButton,
ArrayField,
ImageField,
ShowButton,
RefreshButton,
CreateButton,
ExportButton,
NumberField,
} from "react-admin";
import { Fragment } from "react";
const UserBulkActionButtons = (props) => (
<Fragment>
<BulkDeleteWithConfirmButton {...props} />
</Fragment>
);
const ShopList = (props) => {
return (
<List
{...props}
filters={<ShopFilter />}
actions={<ProductActionsButtons />}
bulkActionButtons={<UserBulkActionButtons />}
style={{ width: "80%" }}
>
<Datagrid rowClick="show">
<NumberField source="id" />
<TextField source="title" />
<ArrayField source="items">
<Datagrid rowClick="edit">
{" "}
<TextField source="id" />
<TextField source="name" />
<TextField source="description" />
<ImageField source="imageUrl" />{" "}
<NumberField label="in Stock" source="amount" />
<NumberField source="price" />
<ShowButton label="" />
<EditButton />
<DeleteWithConfirmButton />
</Datagrid>
</ArrayField>
<CreateButton />
{/* <EditButton /> */}
</Datagrid>
</List>
);
};
const ShopFilter = (props) => (
<Filter {...props}>
<TextInput label="Search" source="q" alwaysOn />
{/* <ReferenceInput label="Title" source="userId" reference="users" allowEmpty>
<SelectInput optionText="name" />
</ReferenceInput> */}
</Filter>
);
const ProductActionsButtons = (props) => (
<div>
<RefreshButton {...props} />
<CreateButton {...props} />
<ExportButton {...props} />
</div>
);
export default ShopList;
import React from "react";
import {
Edit,
ImageField,
SimpleForm,
TextInput,
Datagrid,
ArrayField,
TextField,
ImageInput,
SimpleFormIterator,
ArrayInput,
Toolbar,
SaveButton,
DeleteWithConfirmButton,
NumberInput,
required,
} from "react-admin";
const ShopEdit = (props) => {
return (
<Edit {...props} title={<ShopTitle />} undoable={false}>
<SimpleForm toolbar={<ProductEditToolbar />}>
<TextInput disabled source="id" />
<TextInput label="Category" source="title" validate={[required()]} />
<ArrayInput source="items">
<SimpleFormIterator>
<TextInput
label="Product Name"
source="name"
validate={[required()]}
/>
<TextInput
label="Product Description"
source="description"
validate={[required()]}
/>
<ImageInput label="Product Image Url" source="imageUrl" />
{/* <TextInput label="Product Price" source="price" /> */}
<NumberInput min="0" step="1" label="in Stock" source="amount" />
<NumberInput
label="Product Price"
min="0.01"
step="0.01"
source="price"
validate={[required()]}
/>
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Edit>
);
};
const ShopTitle = ({ record }) => {
return <span>{record ? `Product "${record.name}"` : ""}</span>;
};
const ProductEditToolbar = (props) => (
<Toolbar {...props}>
<SaveButton />
<DeleteWithConfirmButton />
</Toolbar>
);
export default ShopEdit;

Make <TabPanel> content full width and hight as parent

I am using React with material-ui. I am using appbar with tabs and I want to be able when I pick some of the tabs the content of the tab to be full width and height.
Here is the sandbox example: https://codesandbox.io/s/vigorous-cookies-4dmf2?file=/src/App.js
As you can see the provided picture the content of the tab does not fill the whole page under the bar. How I can do it to fill it?
If you inspect your marked div in your screenshot. You will find out the padding style is related to MuiTabPanel-root. On Material's official website, they introduced a few ways to override component's styles. Here is one of the ways you can do, to overide component's style by rule names. You can also find each component's rule name under Component API section on their website.
const useStyles = makeStyles({
tabPanelRoot: {
padding: 0
},
});
usage:
export default function App() {
const classes = useStyles();
return(
...
<TabPanel value="1" classes={{ root: classes.tabPanelRoot}}>
...
)
}
See edited code here.
since the parent container is not of full height so, the tanpanel is not of full height. to make the tabpanel of full height pass a class to the root of the tabpanel. Pass the required height to tabpanelRoot class. (here I've neglected the height of the appbar)
export default function App() {
const classes= useStyles()
const [value, setValue] = React.useState("1");
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Box style={{height:'100%', background:'red'}}>
<TabContext value={value}>
<AppBar position="static">
<TabList
variant="scrollable"
onChange={handleChange}
aria-label="simple tabs example"
>
<Tab label="Business Info" value="1" icon={<ContactMailIcon />} />
<Tab label="Financial" value="2" icon={<MonetizationOnIcon />} />
<Tab label="Participants" value="3" icon={<AccessibilityIcon />} />
</TabList>
</AppBar>
<Box style={{height:'100%', background:'red'}}>
<TabPanel value="1" classes={{root:classes.tabpanelRoot}}>
<Box style={{height:'100%', backgroundColor: "red" }}>Content 1</Box>
</TabPanel>
<TabPanel value="2" classes={{root:classes.tabpanelRoot}}>
<Box style={{height:'100%', backgroundColor: "green" }}>Content 2</Box>
</TabPanel>
<TabPanel value="3" classes={{root:classes.tabpanelRoot}}>
<Box style={{height:'100%', backgroundColor: "blue" }}>Content 3</Box>
</TabPanel>
</Box>
</TabContext>
</Box>
);
}
const useStyles = makeStyles((theme) => ({
tabpanelRoot: {
padding:0,
height: `calc(100vh - 52px)`
},
}));
Here is the codesandbox link:- https://codesandbox.io/s/angry-noether-huxvz
Try this
Updated code with useStyle hook.
App.js
import React from "react";
import "./styles.css";
import AppBar from "#material-ui/core/AppBar";
import Tab from "#material-ui/core/Tab";
import TabContext from "#material-ui/lab/TabContext";
import TabList from "#material-ui/lab/TabList";
import TabPanel from "#material-ui/lab/TabPanel";
import Box from "#material-ui/core/Box";
import MonetizationOnIcon from "#material-ui/icons/MonetizationOn";
import ContactMailIcon from "#material-ui/icons/ContactMail";
import AccessibilityIcon from "#material-ui/icons/Accessibility";
import { makeStyles } from "#material-ui/core";
const useStyles = makeStyles({
appContainer: {
display: "flex",
flexDirection: "column",
width: "100vw",
height: "100vh"
},
container: {
display: "flex",
height: "100%",
width: "100%"
},
panel: {
width: "100%"
}
});
export default function App() {
const [value, setValue] = React.useState("1");
const classes = useStyles();
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Box className={classes.appContainer}>
<TabContext value={value}>
<AppBar position="static">
<TabList
variant="scrollable"
onChange={handleChange}
aria-label="simple tabs example"
>
<Tab label="Business Info" value="1" icon={<ContactMailIcon />} />
<Tab label="Financial" value="2" icon={<MonetizationOnIcon />} />
<Tab label="Participants" value="3" icon={<AccessibilityIcon />} />
</TabList>
</AppBar>
<Box className={classes.container}>
<TabPanel value="1" className={classes.panel}>
<Box
className={classes.container}
style={{ backgroundColor: "red" }}
>
Content 1
</Box>
</TabPanel>
<TabPanel value="2" className={classes.panel}>
<Box style={{ backgroundColor: "green" }} className={classes.container} >Content 2</Box>
</TabPanel>
<TabPanel value="3" className={classes.panel}>
<Box className={classes.container} style={{ backgroundColor: "blue" }}>Content 3</Box>
</TabPanel>
</Box>
</TabContext>
</Box>
);
}
Here is the sandbox link - https://codesandbox.io/s/shy-voice-nih2s
import * as React from 'react';
import Box from '#mui/material/Box';
import Tab from '#mui/material/Tab';
import TabContext from '#mui/lab/TabContext';
import TabList from '#mui/lab/TabList';
import TabPanel from '#mui/lab/TabPanel';
export default function LabTabs() {
const [value, setValue] = React.useState('1');
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<Box sx={{ width: '100%', typography: 'body1' }}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={handleChange} aria-label="lab API tabs example">
<Tab label="Item One" value="1" />
<Tab label="Item Two" value="2" />
<Tab label="Item Three" value="3" />
</TabList>
</Box>
<TabPanel sx={{pl: 1,pt:1}} value="1">Item One</TabPanel>
<TabPanel sx={{pl: 1,pt:1}} value="2">Item Two</TabPanel>
<TabPanel sx={{pl: 1,pt:1}} value="3">Item Three</TabPanel>
</TabContext>
</Box>
);
}
Tabs Height can be changed by .MuiTabs-root
const AntTab = styled((props: StyledTabProps) => (
<Tab disableRipple {...props} />
))(() => ({
**minHeight: '33px',
maxHeight: '33px',**
color: '#718296',
fontFamily: 'Montserrat',
}))

Categories

Resources