Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Limpando formulário após adicionar nova nota.

Boa tarde!

Informação importante: Já finalizei o curso e o projeto está funcional.

Problema principal:

Estou tentando fazer com o que o formulário tenha os campos limpos após a chamada do onSubmit, mas não estou encontrando uma abordagem que funcione.

Solução pensada:

Adicionar dentro do this.state da classe FormularioCadastro as propriedades de titulo e descricao, passando a referenciar o value dos inputs olhando diretamente para essas propriedades.

// Alteração no construtor:
  constructor(props) {
    super(props);
    this.titulo = "";
    this.descricao = "";
    this.categoria = "Sem Categoria";

    // Adicionando os valores inicias
    this.state = { titulo: '', descricao: '', 
    categorias: [] };
    this._novasCategorias = this._novasCategorias.bind(this);
  }

       <input
          className="form-cadastro_input"
          type="text"
          placeholder="Título"
          value={this.state.titulo}  // Aqui em teoria entra o value dinâmico.
          onChange={this._handleMudancaTitulo.bind(this)}
        />

        <textarea
          className="form-cadastro_input"
          rows={15}
          placeholder="Escreva sua nota..."
          value={this.state.descricao} // Aqui em teoria entra o value dinâmico.
          onChange={this._handleMudancaDescricao.bind(this)}
        />

Isso com o intuito de manipular o estado dessas informações, adicionando dentro da função de criarNota, a chamada de uma segunda função que altera o estado dos valores para uma string vazia.

// Alteração na função que chama a função da classe pai, chamando a função que limpa os campos.
    _criarNota(event) {
    event.preventDefault();
    event.stopPropagation();
    this.props.criarNota(this.titulo, this.descricao, this.categoria);
    this._limparFormulario();
  }

 // Alterando o estado do título e descrição.
  _limparFormulario() {
    this.setState = {...this.state, titulo: '', descricao: ''}
  }

Problema da solução:

Ao determinar a propriedade value dos inputs, eles simplesmente perdem a capacidade de receberem novos valores, literalmente não é mais possível digitar para substituir o valor nos inputs. E mesmo não tendo alteração visual, ao clicar no submit do form, apenas a última tecla pressionada dentro dos campos parece ser computada.

valores estranhos no resultado quando o form esta com value setado para propriedades do state

Mesmo ignorando esse problema, ainda sim a mudança dos inputs para vazio após o onSubmit acaba não acontecendo.

2 respostas
solução!

Fala Gabriel, tudo bem?

O melhor seria fazer isso mesmo, e isso se chama Componente Controlado você pode ver sobre isso clicando aqui para acessar a documentação original do react, mas se baseia em utilizar os estados como valores dos inputs do seu formulário para que seja controlado pelo React, bem o que você está fazendo mesmo, então o que você deve fazer é setar o estado como value do seu input (assim como você fez) e no onChange desse input deve haver uma função que faça a alteração desse estado, então na função que você está passando para o onChange deve fazer essa alteração do estado para que quando digitarmos ja aparecer no input, como por exemplo:

constructor(props) {
    super(props);
    this.state = { titulo: '', descricao: '', 
    categorias: [] };
  }

    handleChangeTitulo(e) {
         this.setState({ ...this.state, this.titulo: e.target.value })
    }

    handleChangeDescricao(e) {
         this.setState({ ...this.state, this.descricao: e.target.value })
    }

    render() {
        return (
                <input
                        className="form-cadastro_input"
                        type="text"
                        placeholder="Título"
                        value={this.state.titulo}  // Aqui em teoria entra o value dinâmico.
                        onChange={this._handleChangeTitulo}
                    />

                <textarea
                        className="form-cadastro_input"
                        rows={15}
                        placeholder="Escreva sua nota..."
                        value={this.state.descricao} // Aqui em teoria entra o value dinâmico.
                        onChange={this._handleChangeDescricao}
                />
        )
    }

Logo acima criamos duas funções, uma em que fazemos a alteração do estado de ambos os campos de acordo com o que passamos no onChange, então quando o usuário digitar irá alterar o valor do input normalmente e você pode usar esse valor do estado e o setState para limpar o estado como estava fazendo.

Então o que você deve fazer é ter certeza de que a função que você está chamando esteja fazendo essa alteração no estado.

Espero ter ajudado, bons estudos :D

Muito obrigado pela resposta Mateus!

Eu não havia me atentado para o onChange, já que originalmente o projeto aponta para as propriedades criadas no construtor, faltando ajustar para olharem para o this.state.

Quanto a sua solução, ficaram só 2 detalhes:

No caso da chamada do setState, ao invés de atribuir, abrir parenteses para a chamada da função (esse erro estava no meu código anterior, só me atentei depois da sua resposta):

this.setState = { }; // Erro de compilação.
this.setState({ });   // Compila sem erros.

E também na atribuição dentro dos handles, somente tirando o this.

this.setState({ ...this.state, titulo: e.target.value })

Estou deixando o código da classe disponível para quem tiver curiosidade ou passou pelo mesmo perrengue!

import React, { Component } from 'react';
import './style.css';

class FormularioCadastro extends Component {

  constructor(props) {
    super(props);
    this.titulo = "";
    this.descricao = "";
    this.categoria = "Sem Categoria";
    this.state = { titulo: '', descricao: '', categorias: [] };
    this._novasCategorias = this._novasCategorias.bind(this);
  }

  componentDidMount() {
    this.props.categorias.inscrever(this._novasCategorias); 
  }

  componentWillUnmount() {
    this.props.categorias.desinscrever(this._novasCategorias);
  }

  _novasCategorias(categorias) {
    this.setState({...this.state, categorias})
  }

  _handleMudancaTitulo(event) {
    event.stopPropagation();
    this.setState({...this.state, titulo: event.target.value});
  }

  _handleMudancaDescricao(event) {
    event.stopPropagation();
    this.setState({...this.state, descricao: event.target.value});
  }

  _handleMudancaCategoria(event) {
    event.stopPropagation();
    this.categoria = event.target.value;
  }

  _criarNota(event) {
    event.preventDefault();
    event.stopPropagation();
    this.props.criarNota(this.state.titulo, this.state.descricao, this.categoria);
    this._limparFormulario();
  }

  _limparFormulario() {
    this.setState({...this.state, titulo: '', descricao: ''});
  }

  render() {
    return (
      <form className="form-cadastro"
        onSubmit={this._criarNota.bind(this)}>

        <select 
          className="form-cadastro_input"
          onChange={this._handleMudancaCategoria.bind(this)}
        >
          <option>Sem categoria</option>
          {this.state.categorias.map((categoria, index) => {
            return <option key={index}>{categoria}</option>
          })}
        </select>

        <input
          className="form-cadastro_input"
          type="text"
          placeholder="Título"
          onChange={this._handleMudancaTitulo.bind(this)}
          value={this.state.titulo}
        />

        <textarea
          className="form-cadastro_input"
          rows={15}
          placeholder="Escreva sua nota..."
          onChange={this._handleMudancaDescricao.bind(this)}
          value={this.state.descricao}
        />

        <button className="form-cadastro_input form-cadastro_submit">
          Criar Nota
        </button>

      </form>
    );
  }
}

export default FormularioCadastro;