Home > Back-end >  Right/Best way of accessing component properties in parent component
Right/Best way of accessing component properties in parent component

Time:01-21

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}
      />
    </>
  );
};
  • Related