La propiedad 'value' no existe en el tipo 'Readonly <{}>'

155

Necesito crear un formulario que muestre algo basado en el valor de retorno de una API. Estoy trabajando con el siguiente 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>
    );
  }
}

Recibo el siguiente error:

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

Recibí este error en las dos líneas que comenté en el código. Este código ni siquiera es mío, lo obtuve del sitio oficial de reacción ( https://reactjs.org/docs/forms.html ), pero no está funcionando aquí.

Estoy usando la herramienta create-react-app.

Luis Henrique Zimmermann
fuente
Su problema radica en otra parte - vea esta demostración
Ted
Lo sé, está funcionando en todos estos sitios web de "compiladores", pero me recomendaron usar esto para hacer el proyecto github.com/Microsoft/TypeScript-React-Starter , y a través del compilador TypeScript, no está funcionando
Luis Henrique Zimmermann

Respuestas:

264

El Component se define así:

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

Lo que significa que el tipo predeterminado para el estado (y apoyos) es: {}.
Si desea que su componente tenga valueel estado, debe definirlo así:

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

O:

type MyProps = { ... };
type MyState = { value: string };
class App extends React.Component<MyProps, MyState> {
    ...
}
Nitzan Tomer
fuente
3
Dios mío, amigo, funcionó ahora, solo respóndeme una cosa más, esta sintaxis está relacionada con TypeScript, ¿verdad? porque en reaccionar sitio oficial no tiene nada similar
Luis Henrique Zimmermann
3
Sí, esto está estrictamente relacionado con la mecanografía.
Nitzan Tomer
1
La definición correcta es: class Square extiende React.Component <{value: string}, {}> {...}
Rodrigo Perez Burgues
58

Además de la respuesta de @ nitzan-tomer, también tiene la opción 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);
  ...
};

Cualquiera de los dos está bien, siempre y cuando seas consistente.

León
fuente
1
Resuma lo que significa coherente en el contexto de su publicación para que sea posible tener su valor completo sin la necesidad de leer el artículo del medio (que es un excelente enlace útil, gracias).
Karl Richter
9

El problema es que no ha declarado el estado de su interfaz, reemplace ninguno con su tipo de variable adecuada del 'valor'

Aquí hay una buena referencia

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

interface AppState {
   value: any
}

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

event.targetes de tipo EventTargetque no siempre tiene un valor. Si es un elemento DOM, debe convertirlo al tipo correcto:

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

Esto inferirá también el tipo "correcto" para la variable de estado, aunque probablemente sea mejor ser explícito

apokryfos
fuente
Creo que recibe el error cuando intenta inicializar la cadena en el constructor, no en el controlador de eventos
Ray_Poly