Подтвердить что ты не робот

Значение datetime-local с React

Я делаю свой первый проект с React, и я ударил стену, как использовать локальное поле datetime, используя обычную логику React.

Для любого заданного поля ввода я бы сделал, как описано в React documentation.

Проблема для меня в том, что поле datetime-local имеет некоторые досадные возвращаемые значения. Он возвращает пустую строку в случаях два. Один случай - когда вы используете встроенную кнопку очистки, а в другом случае - когда установлена ​​недопустимая дата - например, 29 февраля 2015 года.

Так как это так, я не могу просто установить значение поля равным значению event.target.value, так как это будет reset поле каждый раз, когда кто-то нажимает на недопустимую дату. Если я скажу ему ничего не делать, когда сталкивается с пустым возвращаемым значением, это означает, что вы больше не можете использовать кнопку очистки в поле.

Мне не удалось найти что-либо, связанное с этой проблемой, поэтому я надеюсь, что у кого-то есть идея решить ее.

4b9b3361

Ответ 1

Я решил это на данный момент, установив значение, используя атрибут JSX "defaultValue" вместо "value".

Это приводит к тому, что поле не блокируется переменной состояния, что, в свою очередь, позволяет мне сделать функцию onChange, которая всегда обновляет состояние, но не оказывает никакого влияния на само поле.

Таким образом, поле ведет себя так, как ожидалось, и я могу просто отправить любое значение в мое состояние.

Недостатком этого решения является то, что я не могу подтвердить дату. Это означает, что если кто-то пытается отправить недействительную дату, он будет просто сохранен как нуль в базе данных.

Если кто-нибудь придумает более элегантное решение, я был бы рад услышать его.

Ответ 2

Отредактируйте исправление getDay для getDate, так как getDay возвращает день недели, а getDate возвращает день месяца.

  <input
    type="datetime-local"
    value={this.state.datetime}
    onChange={e => this.handleChange('datetime', e)}
   />

Поскольку это контролируемый компонент, вы должны установить значение состояния для чтения. Я устанавливаю текущую дату и время в таком состоянии...

state = {
      datetime: '${new Date().getFullYear()}-${'${new Date().getMonth() +
        1}'.padStart(2, 0)}-${'${new Date().getDate() + 1}'.padStart(
        2,
        0
      )}T${'${new Date().getHours()}'.padStart(
        2,
        0
      )}:${'${new Date().getMinutes()}'.padStart(2, 0)}'
  };

и мой handleChange можно использовать для других текстовых вводов, например так:

handleChange = (field, e) => {
    this.setState({ [field]: e.target.value });
  };

Ответ 3

Изменить мое изменение, не добавляйте 1 к дню месяца

Отредактируйте в josh answer, чтобы исправить getDay для getDate, поскольку getDay возвращает день недели, а getDate возвращает день месяца.

<input
type="datetime-local"
value={this.state.datetime}
onChange={e => this.handleChange('datetime', e)}
/>

Поскольку это контролируемый компонент, вы должны установить значение состояния для чтения. Я устанавливаю текущую дату и время в таком состоянии...

state = {
  datetime: '${new Date().getFullYear()}-${'${new Date().getMonth() +
    1}'.padStart(2, 0)}-${'${new Date().getDate()}'.padStart(
    2,
    0
  )}T${'${new Date().getHours()}'.padStart(
    2,
    0
  )}:${'${new Date().getMinutes()}'.padStart(2, 0)}'
  };

и мой handleChange можно использовать повторно для других текстовых вводов, например так:

handleChange = (field, e) => {
    this.setState({ [field]: e.target.value });
};

Ответ 4

Хитрость для решения этой проблемы заключается в использовании свойства .validity.valid поля ввода (см. https://developer.mozilla.org/en-US/docs/Web/API/ValidityState). Если это false, не обновляйте состояние React. Это может выглядеть так:

const [ datetime, setDatetime ] = useState('');

<input type="datetime-local"
  value={(datetime || '').toString().substring(0, 16)}
  onChange={handleChange} />

function handleChange(ev) {
  if (!ev.target['validity'].valid) return;
  const dt= ev.target['value'] + ':00Z';
  setDatetime(dt);
}