Невозможно установить состояние текстового поля на неопределенное с помощью React hook

#reactjs #typescript #material-ui #react-hooks #react-state-management

#reactjs #typescript #материал-пользовательский интерфейс #реагирующие перехваты #управление состоянием реакции

Вопрос:

Я хотел бы, чтобы начальное состояние для даты TextField было установлено до undefined тех пор, пока пользователь не выберет дату, а затем позволит пользователю легко сбросить дату обратно undefined .

В следующем коде кнопка сброса правильно сбросит parameters.count состояние 0 , но оно не будет сброшено parameters.date undefined . undefined Обрабатывается ли это специально в этом случае?

 import React, { useState } from "react";
import { Button, TextField } from "@material-ui/core";

import "./App.css";

export type Parameters = {
  count: number;
  date?: string;
};

const initialParameters: Parameters = {
  count: 0,
  date: undefined,
};

export const App: React.FC = () => {
  const [parameters, setParameters] = useState<Parameters>(initialParameters);

  const handleCountChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setParameters({
      ...parameters,
      count: Number(event.target.value),
    });
  };

  const handleDateChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setParameters({
      ...parameters,
      date: event.target.value,
    });
  };

  const resetState = () => {
    setParameters(initialParameters);
  };

  return (
    <div className="App">
      <TextField
        type="number"
        label="Count"
        value={parameters.count}
        onChange={handleCountChange}
      />
      <TextField
        label="Date"
        type="date"
        value={parameters.date}
        onChange={handleDateChange}
        InputLabelProps={{
          shrink: true,
        }}
      />
      <Button onClick={resetState}>Reset</Button>
    </div>
  );
};
  

Комментарии:

1. Я думаю, что это скорее случай, когда компонент текстового поля не принимает значение undefined в качестве значения (вместо этого должна быть пустая строка). На самом деле удивительно, что он не показывает предупреждение о том, что ввод меняется с контролируемого на неконтролируемый, но, возможно, Material UI не показывает эти предупреждения.

2. Фактически, <input type="date"> спецификация предполагает , что если значение является недопустимой строкой даты, значение устанавливается в пустую строку: » Если значение элемента не является допустимой строкой даты, то вместо этого установите его в пустую строку». Попробуйте установить начальное значение date to '' вместо undefined .

3. Настройка date: "", сработала, спасибо. Я предполагаю, что я пытался использовать систему типов для кодирования «отсутствующего» значения, но это похоже на TextField желания "" .

Ответ №1:

Решение, основанное на комментарии @cbr, заключается в принудительном undefined "" использовании перед переходом к TextField .

 import React, { useState } from "react";
import { Button, TextField } from "@material-ui/core";

import "./App.css";

export type Parameters = {
  count: number;
  date?: string;
};

const initialParameters: Parameters = {
  count: 0,
  date: undefined,
};

export const App: React.FC = () => {
  const [parameters, setParameters] = useState<Parameters>(initialParameters);

  const handleCountChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setParameters({
      ...parameters,
      count: Number(event.target.value),
    });
  };

  const handleDateChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setParameters({
      ...parameters,
      date: event.target.value,
    });
  };

  const resetState = () => {
    setParameters(initialParameters);
  };

  // TextField expects blank string to represent no value.
  const dateDisplay = parameters.date ? parameters.date : "";
  return (
    <div className="App">
      <TextField
        type="number"
        label="Count"
        value={parameters.count}
        onChange={handleCountChange}
      />
      <TextField
        label="Date"
        type="date"
        value={dateDisplay}
        onChange={handleDateChange}
        InputLabelProps={{
          shrink: true,
        }}
      />
      <Button onClick={resetState}>Reset</Button>
    </div>
  );
};