E
E
EvgenJunior2021-06-07 17:21:35
typescript
EvgenJunior, 2021-06-07 17:21:35

Why does component auto-render using DateTimePicker from material-ui/pickers?

Good afternoon, colleagues!
In the project, I use the material-ui/pickers library. I need to implement a search in a table by the user's registration date. I applied the DateTimePicker component. There is a date FROM the DateTimePicker (one component), a date AFTER (the second component)
There was a problem: one date is selected, then the second, and autorun immediately works. When one of the dates is selected, the modal window does not close, it waits for the user's action. At the first, then the second date (the order does not matter), autorun is triggered.
The question is, is there some kind of slide effect in the DateTimePicker component that I don't know about?
I'll be glad for any hint.
PS Below is the code of my component, maybe it will help to clarify the situation

import React, { useEffect, useState } from 'react';
import ClearIcon from '@material-ui/icons/Clear';
import ukLocale from 'date-fns/locale/uk';
import { DateTimePicker, MuiPickersUtilsProvider } from '@material-ui/pickers';
import DateFnsUtils from '@date-io/date-fns';
import {
  Box,
  createStyles,
  IconButton,
  makeStyles,
  Theme,
  Typography
} from '@material-ui/core';
import { useHistory } from 'react-router-dom';
import {
  useBuildUrlWithoutGetParameter,
  useGetParameter,
  useSetGetParameter
} from '../../../general/hooks/get-parameter.hook';
import { usePreviousValue } from '../../../general/hooks/previous-value.hook';
import { TDateSearch } from '../type';

interface IDateSearch {
  dataKey: string;
  inDateValue: TDateSearch;
}

const useStyles = makeStyles((theme: Theme) => {
  return createStyles({
    dataTimePicker: {
      width: '300px',
      paddingRight: '14px'
    },
    box: {
      display: 'flex'
    }
  });
});

export const SearchDate: React.FC<IDateSearch> = ({ dataKey, inDateValue }) => {
  const classes = useStyles();
  const beforeDateKey = `${dataKey}[before]`;
  const afterDateKey = `${dataKey}[after]`;
  const getParameterBefore = useGetParameter(`${beforeDateKey}`);
  const getParameterAfter = useGetParameter(`${afterDateKey}`);

  // инициализация стартового значения для state
  const initFromDateValue =
    getParameterBefore === null
      ? inDateValue.fromCreateDate
      : new Date(getParameterBefore);

  const initToDateValue =
    getParameterAfter === null
      ? inDateValue.fromCreateDate
      : new Date(getParameterAfter);

  // state для получения данных из DataTimePicker
  const [
    selectedBeforeCreateDate,
    setSelectedBeforeCreateDate
  ] = useState<Date | null>(initFromDateValue);
  const [
    selectedAfterCreateDate,
    setSelectedAfterCreateDate
  ] = useState<Date | null>(initToDateValue);

  const prevValueBeforeCreateDate = usePreviousValue(selectedBeforeCreateDate);
  const prevValueAfterCreateDate = usePreviousValue(selectedAfterCreateDate);

  const history = useHistory();

  const dateValue = (arg: Date | null) => {
    if (arg !== null) {
      return arg.toISOString();
    }
    return '';
  };

  const getParametersBefore = {
    [beforeDateKey]: dateValue(selectedBeforeCreateDate)
  };
  const getParametersAfter = {
    [afterDateKey]: dateValue(selectedAfterCreateDate)
  };

  const urlBefore = useSetGetParameter(getParametersBefore);
  const urlAfter = useSetGetParameter(getParametersAfter);
  const urlBeforeWithoutGetParameter = useBuildUrlWithoutGetParameter([
    beforeDateKey
  ]);
  const urlAfterWithoutGetParameter = useBuildUrlWithoutGetParameter([
    afterDateKey
  ]);

  const DateBeforeChange = (date: Date | null) => {
    setSelectedBeforeCreateDate(date);
  };
  const DateAfterChange = (date: Date | null) => {
    setSelectedAfterCreateDate(date);
  };

  useEffect(() => {
    if (
      prevValueBeforeCreateDate?.toISOString() ===
      selectedBeforeCreateDate?.toISOString()
    ) {
      if (selectedBeforeCreateDate === null) {
        history.push(urlBeforeWithoutGetParameter);
      } else {
        history.push(urlBefore);
      }
    }
  }, [
    history,
    prevValueBeforeCreateDate,
    selectedBeforeCreateDate,
    urlBefore,
    urlBeforeWithoutGetParameter
  ]);

  useEffect(() => {
    if (
      prevValueAfterCreateDate?.toISOString() ===
      selectedAfterCreateDate?.toISOString()
    ) {
      if (selectedAfterCreateDate !== null) {
        history.push(urlAfter);
      } else {
        history.push(urlAfterWithoutGetParameter);
      }
    }
  }, [
    history,
    prevValueAfterCreateDate,
    selectedAfterCreateDate,
    urlAfter,
    urlAfterWithoutGetParameter
  ]);

  const resetBeforeDate = (event: React.MouseEvent<HTMLButtonElement>) => {
    event.stopPropagation();
    setSelectedBeforeCreateDate(null);
  };
  const resetAfterDate = (event: React.MouseEvent<HTMLButtonElement>) => {
    event.stopPropagation();
    setSelectedAfterCreateDate(null);
  };

  return (
    <Box>
      <Typography align='center' component='h5'>
        Поиск по дате создания
      </Typography>
      <MuiPickersUtilsProvider utils={DateFnsUtils} locale={ukLocale}>
        <DateTimePicker
          margin='normal'
          inputVariant='outlined'
          className={classes.dataTimePicker}
          autoOk={false}
          ampm={false}
          disableFuture
          value={selectedBeforeCreateDate}
          onChange={DateBeforeChange}
          label='З'
          okLabel='Подтвердить'
          cancelLabel='Отменить'
          clearLabel='Очистить'
          InputLabelProps={{ style: { fontSize: '20px' } }}
          format='yyyy-MM-dd HH:mm:ss'
          clearable
          variant='dialog'
          invalidDateMessage='Недопустимый формат'
          maxDateMessage='Дата не должна быть позже максимальной даты'
          maxDate={selectedAfterCreateDate}
          InputProps={{
            endAdornment: (
              <IconButton onClick={resetBeforeDate}>
                <ClearIcon />
              </IconButton>
            )
          }}
        />
        <DateTimePicker
          margin='normal'
          inputVariant='outlined'
          className={classes.dataTimePicker}
          autoOk={false}
          ampm={false}
          minDate={selectedBeforeCreateDate}
          disableFuture
          value={selectedAfterCreateDate}
          onChange={DateAfterChange}
          label='До'
          okLabel='Подтвердить'
          cancelLabel='отменить'
          clearLabel='Очистить'
          InputLabelProps={{ style: { fontSize: '20px' } }}
          format='yyyy-MM-dd HH:mm:ss'
          maxDateMessage='Дата не должна быть позже максимальной даты'
          clearable
          variant='dialog'
          InputProps={{
            endAdornment: (
              <IconButton onClick={resetAfterDate}>
                <ClearIcon />
              </IconButton>
            )
          }}
        />
      </MuiPickersUtilsProvider>
    </Box>
  );
};

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question