A propriedade 'value' não existe no tipo 'Readonly <{}>'

155

Eu preciso criar um formulário que exibirá algo com base no valor de retorno de uma API. Estou trabalhando com o seguinte código:

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>
    );
  }
}

Estou recebendo o seguinte erro:

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

Eu recebi esse erro nas duas linhas que comentei no código. Esse código nem é meu, eu o peguei no site oficial do react ( https://reactjs.org/docs/forms.html ), mas não está funcionando aqui.

Estou usando a ferramenta create-react-app.

Luis Henrique Zimmermann
fonte
Seu problema está em outro lugar - veja esta demonstração
Ted
eu sei, ele está trabalhando em todos esses sites de "compiladores", mas eles me aconselharam a usá-lo para fazer o projeto github.com/Microsoft/TypeScript-React-Starter e, através do complemento TypeScript, não está funcionando
Luis Henrique Zimmermann

Respostas:

264

O Component é definido assim:

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

O que significa que o tipo padrão para o Estado (e adereços) é: {}.
Se você deseja que seu componente tenha valueno estado, é necessário defini-lo assim:

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

Ou:

type MyProps = { ... };
type MyState = { value: string };
class App extends React.Component<MyProps, MyState> {
    ...
}
Nitzan Tomer
fonte
3
omg, ty cara, funcionou agora, apenas me responda mais uma coisa, essa sintaxe está relacionada ao TypeScript, certo? porque no site oficial do react ele não tem nada parecido
Luis Henrique Zimmermann
3
Sim, isso está estritamente relacionado ao texto datilografado.
Nitzan Tomer
1
O direito definir é: class Praça estende React.Component <{value: string}, {}> {...}
Rodrigo Perez Burgues
58

Além da resposta do @ nitzan-tomer, você também tem a opção de usar inferfaces :

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);
  ...
};

Ou é bom, desde que você seja consistente.

Leo
fonte
1
Resuma o que significa consistente no contexto de sua postagem, para que seja possível ter todo o seu valor sem a necessidade de ler o artigo médio (que é um ótimo link útil, obrigado).
Karl Richter
9

O problema é que você não declarou que o estado da interface substitui nenhum pelo seu tipo de variável adequado do 'valor'

Aqui está uma boa referência

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

interface AppState {
   value: any
}

class App extends React.Component<AppProps, AppState> {
  // ...
}
Minuka ArTy Weerathunga
fonte
0

event.targeté do tipo EventTargetque nem sempre tem um valor. Se for um elemento DOM, você precisará convertê-lo para o tipo correto:

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

Isso inferirá o tipo "correto" para a variável state, embora seja explícito provavelmente seja melhor

apokryfos
fonte
Eu acho que ele recebe o erro quando tenta inicializar a string no construtor, não no manipulador de eventos
Ray_Poly