Свойство 'value' не существует для типа 'Readonly <{}>'

155

Мне нужно создать форму, которая будет отображать что-то на основе возвращаемого значения API. Я работаю со следующим кодом:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value); //error here
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} /> // error here
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Я получаю следующую ошибку:

error TS2339: Property 'value' does not exist on type 'Readonly<{}>'.

Я получил эту ошибку в двух строках, которые комментировал код. Этот код даже не мой, я получил его с официального сайта реакции ( https://reactjs.org/docs/forms.html ), но здесь он не работает.

Я использую инструмент создания-реакции-приложения.

Луис Энрике Циммерманн
источник
Ваша проблема лежит в другом месте - см. Это демо
Тед
я знаю, он работает на всех этих «компиляторных» сайтах, но они посоветовали мне использовать это для выполнения проекта github.com/Microsoft/TypeScript-React-Starter , а через компилятор TypeScript он не работает
Луис Энрике Циммерманн

Ответы:

264

Component Определяется следующим образом:

interface Component<P = {}, S = {}> extends ComponentLifecycle<P, S> { }

Это означает , что тип по умолчанию для государства (и реквизита) является: {}.
Если вы хотите, чтобы ваш компонент valueнаходился в состоянии, вам нужно определить его следующим образом:

class App extends React.Component<{}, { value: string }> {
    ...
}

Или:

type MyProps = { ... };
type MyState = { value: string };
class App extends React.Component<MyProps, MyState> {
    ...
}
Ницан Томер
источник
3
Боже, чувак, теперь это сработало, просто ответь мне еще раз, этот синтаксис связан с TypeScript, верно? потому что в официальном сайте реакции на это нет ничего похожего
Луис Энрике Циммерманн
3
Да, это строго связано с машинописью.
Ницан Томер
1
Правильное определение: класс Square расширяет React.Component <{value: string}, {}> {...}
Родриго Перес Бургес,
58

В дополнение к ответу @ nitzan-tomer у вас также есть возможность использовать внешние интерфейсы :

interface MyProps {
  ...
}

interface MyState {
  value: string
}

class App extends React.Component<MyProps, MyState> {
  ...
}

// Or with hooks, something like

const App = ({}: MyProps) => {
  const [value, setValue] = useState<string>(null);
  ...
};

Либо хорошо, если вы последовательны.

Лео
источник
1
Пожалуйста, подытожите, что означает «непротиворечивый» в контексте вашего поста, чтобы можно было в полной мере оценить его ценность без необходимости читать среднюю статью (которая является отличной полезной ссылкой, спасибо).
Карл Рихтер
9

Проблема в том, что вы не объявили свое состояние интерфейса, замените его подходящим типом переменной 'value'

Вот хорошая ссылка

interface AppProps {
   //code related to your props goes here
}

interface AppState {
   value: any
}

class App extends React.Component<AppProps, AppState> {
  // ...
}
Minuka ArTy Weerathunga
источник
0

event.targetимеет тип, EventTargetкоторый не всегда имеет значение. Если это элемент DOM, вам нужно привести его к правильному типу:

handleChange(event) {
    this.setState({value: (event.target as HTMLInputElement).value});
}

Это также выведет «правильный» тип для переменной состояния, хотя явное, вероятно, лучше

apokryfos
источник
Я думаю, что он получает ошибку, когда пытается инициализировать строку в конструкторе, а не обработчик события
Ray_Poly