Estoy haciendo una aplicación de prueba de reacción simple.

¿Qué es la aplicación? : muestra los nombres de los proyectos y tiene la opción de agregar un nuevo proyecto. Cada proyecto tiene título y categoría.

Así es como se ve

enter image description here

Problema: cuando intento agregar un nuevo proyecto ingresando el título y luego haciendo clic en el botón Enviar, el nuevo nombre del proyecto aparece en los proyectos durante una fracción de segundos y luego desaparece. La lista de proyectos vuelve al estado inicial, que son tres proyectos (que se muestran a continuación)

Este es el código

App.js

import React, { Component } from 'react';

import './App.css';
import Projects from "./Components/Projects"
import AddProjects from './Components/AddProject'

class App extends Component {
  constructor(){
    super();
    this.state = {
      projects:[]
    }
  }

  componentWillMount(){
      this.setState({projects:[
          {
              title: "Trigger",
              category: "Web App"
          },
          {
              title: "Trigger",
              category: "Web App"
          },
          {
              title: "Trigger",
              category: "Web App"
          }
      ]})
  }

  handleAddProject(project){
      let projects = this.state.projects;
      projects.push(project)
      this.setState({projects:projects})
      console.log(this.state.projects)
  }

  render() {
    return (
      <div className="App">
        My Project
          <AddProjects addProject={this.handleAddProject.bind(this)}/>
          <Projects projects={this.state.projects}/>
      </div>
    );
  }
}

export default App;

Projects.js

import React, { Component } from 'react';
import Projectitem from './ProjectItem'


class Projects extends Component {

    render() {
        let projectItems
        if(this.props.projects){
            projectItems = this.props.projects.map(project =>{
                return (
                    <Projectitem project={project}/>
                );
            })
        }
        else{
            console.log("hello")
        }

        return (
            <div>
                This is a list of objects
                {projectItems}
            </div>
        );
    }
}

export default Projects

ProjectItem.js

import React, { Component } from 'react';


class ProjectItem extends Component {
    render() {
        return (

                <li>
                    {this.props.project.title}:{this.props.project.category}
                </li>

        );
    }
}

export default ProjectItem

AddProject.js

import React, { Component } from 'react';


var categories = ["Web dev", "Mobile dev", "websiite"]

class AddProject extends Component {
    constructor(){
        super();
        this.state = {
            newProject:{}
        }
    }


    handleSubmit(){
        this.setState({newProject:{
            title:this.refs.title.value,
            category:this.refs.category.value
        }}, function () {
            this.props.addProject(this.state.newProject)
        })
    }
    render() {
        var categoryOptions = categories.map(category=>{
            return <option key={category} value={category}>{category}</option>
        })
        return (
            <div>
                Add Project <br/>
                <form onSubmit={this.handleSubmit.bind(this)}>
                    <div>
                        <label>title</label><br/>
                        <input type="text" ref="title"/>
                    </div>
                    <div>
                        <label>Category</label><br/>
                        <select ref="category">
                            {categoryOptions}
                        </select>
                    </div>
                    <input type="submit" value="Submit"/>
                </form>
            </div>

        );
    }
}

export default AddProject
1
EdG 18 ene. 2018 a las 18:31

3 respuestas

La mejor respuesta

Agregue event.preventDefault() a su método handleSubmit()

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

Sin ella, su página se actualizará (como lo hace por defecto cuando se envía un formulario)

2
Galupuf 18 ene. 2018 a las 15:33

Estás editando el estado directamente, eso es un gran no-no en React.

Cambie su función de controlador a algo como esto:

handleAddProject(project){
  this.setState((prevState) => {
    return { projects: [...prevState.projects, project] }
  })
}

La función setState se puede llamar usando una 'devolución de llamada', que recibe el estado anterior a su llamada y le permite modificarlo. La parte importante es no mutar el estado directamente (como lo está haciendo su línea projects.push(project)).

Otra opción, que se parece más a lo que ya está intentando hacer, es copiar el estado actual antes de mutarlo:

handleAddProject(project){
  let projects = this.state.projects.slice(); // notice the slice here will return
                                              // a copy of 'projects', and then
                                              // you modify it
  projects.push(project)
  this.setState({projects:projects})
  console.log(this.state.projects)
}

Además, tenga en cuenta que setState se llama asincrónicamente , por lo que la llamada console.log(this.state.projects) puede mostrar el estado anterior todavía, ya que setState aún no se ha llamado.

2
cfraser 18 ene. 2018 a las 15:52

Está utilizando una etiqueta de formulario que se envía información a un servidor web si usa la entrada type = "submit", siempre volverá a cargar la página y el elemento inicial como la primera vez que se cargó. Si haces como @Galupuf funcionará porque el evento.preventDefault (); no permitirá que el navegador se recargue y no se inicializará todo la primera vez que se cargue.

Mi respuesta es que si no está enviando ningún dato a ningún servidor o no está trabajando con un servidor, cambie la etiqueta del formulario para dividir el tipo de entrada = "enviar" para <button onClick={()=>this.handleSubmit()}>Send</button>

 <div>
                <div>
                    <label>title</label><br/>
                    <input type="text" ref="title"/>
                </div>
                <div>
                    <label>Category</label><br/>
                    <select ref="category">
                        {categoryOptions}
                    </select>
                </div>
                  <button onClick={()=>this.handleSubmit()}>Submit</button>
            </div>

Otra sugerencia funciona el valor modificado del estado como @cfraser sugiere que tendrá datos inmutables

0
Angel 18 ene. 2018 a las 16:23
48324874