简体   繁体   中英

Component with form keeps refreshing page in ReactJS

I'm attempting at creating a simple todo app to try to cement some concepts. This app gets some previous todos from a .js file with json object. And every time they get clicked they are deleted from the current app.

Now I wanted to add the ability to add todos, first to the current instance of app itself and afterwards to the file to ensure continuity.

My problem arises adding to the app instance.

When using the component with a form, it all goes south.

I tried putting all the component parts in the App.js main file but still the same result, it refreshes after the alert(value) line.

I've also tried changing the order inside the addTodo function and the alert only works if it's the first line of the function, anywhere else the refresh happens before it. So I assumed it's something about using the state of the app component?

App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import todosData from "./todosData"
import TodoItem from "./TodoItem"
import TodoForm from './TodoForm'
class App extends Component {

    constructor() {
        super()
        this.state = {
            todos: todosData
        }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(id) {
        const allTodos = this.state.todos
        const filtered = allTodos.filter(x => x.id !== id)
        const filtered2 = filtered
        filtered2.push({id:4,text:"HAKUNA MATATA",completed:false   })
        this.setState({todos:filtered2})
        //added testing so that whenever I delete a todo it adds one with "HAKUNA MATATA"
  }

    addTodo(value) {
        alert(value)
        const allTodos = this.state.todos
        const lastTodo = this.state.todos.slice(-1)[0]
        const newId = lastTodo.id + 1
        const newTodo = {id: newId, text: value, completed:false}
        allTodos.push(newTodo)
        this.setState({todos:allTodos})
    }

  render() {
    const todoItems = this.state.todos.map( item =>
      <TodoItem
        key={item.id}
        item={item}
        handleChange={this.handleChange}
      />
    )
        const text = ""
    return (
      <div className="todo-list">
        {todoItems}
                <TodoForm addTodo={this.addTodo}/>
      </div>
        );
  }
}

export default App;

TodoForm.js

import React from 'react'

class TodoForm extends React.Component {
  constructor(props) {
    super(props)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleSubmit(event) {
    this.props.addTodo(this.input.value)
    event.preventDefault() 
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
        </label>
          <input type="text" ref={(input) => this.input = input}/>

      </form>
    )
  }
}

export default TodoForm

Can you guys help me with this? From what I understood preventDefault was supposed to prevent this?

Call the preventDefault method on the event the first thing you do in handleSubmit and it should work.

handleSubmit(event) {
  event.preventDefault() 
  this.props.addTodo(this.input.value)
}

You also need to bind the addTodo method to this in the App constructor.

class App extends Component {
  constructor() {
    super()
    this.state = {
      todos: todosData
    }
    this.handleChange = this.handleChange.bind(this)
    this.addTodo = this.addTodo.bind(this)
  }

  // ...
}

In case anyone comes to this answer from Google: In my case, when I submitted the form, I lazy loaded a component underneath, but it had not been wrapped in <Suspense> . Adding that fixed my issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM