I am actually pretty new in React. I have customized MUI DatePicker component to use in different forms
import { FormControl, FormLabel, TextField } from "@mui/material";
import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { Dayjs } from "dayjs";
import React from "react";
interface DatePickerProps {
label: string;
id:string;
}
const MyDatePicker = (props: DatePickerProps) => {
const [value, setValue] = React.useState<Dayjs | null>(null);
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<FormControl sx={{ m: 1, width: "90%" }} size="small">
<DatePicker
label={props.label}
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
renderInput={(params) => <TextField id={props.id} {...params} size="small" />}
/>
</FormControl>
</LocalizationProvider>
);
};
export default MyDatePicker;
So in any of my component I can use that component straight away and it seems to be working fine.
But my problem is how can I read the value of that DatePicker if we have around 10 different places on the same form I am using that component.
Please help
CodePudding user response:
Idiomatic is to lift state one component up - exactly what MUI is already doing by providing you value, setValue props. Try:
import { FormControl, FormLabel, TextField } from "@mui/material";
import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { Dayjs } from "dayjs";
import React from "react";
interface DatePickerProps {
label: string;
id:string;
value: Dayjs | null;
setValue: (newValue: Dayjs | null) => void;
}
const MyDatePicker = (props: DatePickerProps) => {
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<FormControl sx={{ m: 1, width: "90%" }} size="small">
<DatePicker
label={props.label}
value={props.value}
onChange={props.setValue}
renderInput={(params) => <TextField id={props.id} {...params} size="small" />}
/>
</FormControl>
</LocalizationProvider>
);
};
export default MyDatePicker;
const ComponentWhereYouWantToUseMyDatePicker() => {
const [value, setValue] = React.useState<Dayjs | null>(null);
// Do with value whatever you want.
return (
<MyDatePicker label="Label" id="Id" value={value} setValue={setValue} />
)
}
CodePudding user response:
You could add a callback onDateChange
this way you don't have to elevate your state.
interface DatePickerProps {
label: string;
id: string;
onDateChange?: (newValue: Dayjs | null) => void;
}
const MyDatePicker = (props: DatePickerProps) => {
const [value, setValue] = React.useState<Dayjs | null>(null);
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<FormControl sx={{ m: 1, width: "90%" }} size="small">
<DatePicker
label={props.label}
value={value}
onChange={(newValue) => {
setValue(newValue);
if (props.onDateChange) props.onDateChange(newValue);
}}
renderInput={(params) => (
<TextField id={props.id} {...params} size="small" />
)}
/>
</FormControl>
</LocalizationProvider>
);
};
Which you can use in your Component like so
const Component = () => {
const handleDateChange = (newDate) => {
console.log(newDate);
// whatever you want to do with the value
};
return (
<>
<MyDatePicker
id="someid"
label="my label"
onDateChange={handleDateChange}
/>
</>
);
};