在调用onClick之后,React JS刷新页面

时间:2019-04-25 16:42:29

标签: reactjs

我一直在网上跟踪MERN堆栈教程之一(制作一个简单的todo应用程序),因此决定不按脚本进行操作。我想添加一个按钮以删除特定项目。删除功能运行良好,但是它要求用户单击删除按钮后手动刷新页面,以便查看数据库(MongoDB)中新的元素列表。我希望页面在单击事件后自动刷新,但是我不确定从哪里开始。在react渲染器中有一个表,该表引用一个变量以实际组装表的组件-这是存在删除按钮的地方。这是我的代码:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';

const Todo = props => (
    <tr>
        <td className={props.todo.todo_completed ? 'completed' : ''}>{props.todo.todo_title}</td>
        <td className={props.todo.todo_completed ? 'completed' : ''}>{props.todo.todo_description}</td>
        <td className={props.todo.todo_completed ? 'completed' : ''}>{props.todo.todo_responsible}</td>
        <td className={props.todo.todo_completed ? 'completed' : ''}>{props.todo.todo_priority}</td>
        <td>
            <Link to={"/edit/"+props.todo._id}>Edit</Link>
        </td>
        <td>
            {/* this is where the delete happens */}
            <button onClick={ () =>
                axios.delete('http://localhost:4000/todos/'+props.todo._id)
                    .then(console.log("Deleted: " + props.todo._id))                    
                    .catch(err => console.log(err))
            }
            >Delete</button>
        </td>
    </tr>
)

export default class TodosList extends Component {

    constructor(props) {
        super(props);
        this.state = {todos: []};
    }

    componentDidMount() {
        axios.get('http://localhost:4000/todos/')
            .then(res => {
                this.setState({ todos: res.data });
            })
            .catch(function(err){
                console.log(err);
            })
    }

    todoList() {
        return this.state.todos.map(function(currentTodo, i){
            return <Todo todo={currentTodo} key={i} />;
        })
    }

    render() {
        return (
            <div>
                <h3>Todos List</h3>
                <table className="table table-striped" style={{ marginTop: 20 }} >
                    <thead>
                        <tr>
                            <th>Title</th>
                            <th>Description</th>
                            <th>Responsible</th>
                            <th>Priority</th>
                            <th>Action</th>
                            <th>Remove Item</th>
                        </tr>
                    </thead>
                    <tbody>
                        { this.todoList() }
                    </tbody>
                </table>
            </div>
        )
    }
}

希望在这里的人可以指引我正确的方向。

谢谢

3 个答案:

答案 0 :(得分:2)

TodosList组件中成功删除特定项目后,您可以从Todo组件状态中删除特定项目。为此,您可以

1)在TodosList组件中添加一个方法。

deleteItemHandler = (id) => {
 const updatedTodos = this.state.todos.filter(todo => todo.id !== id);
 this.setState({todos: updatedTodos})
}

2)将方法deleteItemHandler作为道具传递给Todo组件

todoList() {
    return this.state.todos.map((currentTodo, i) => {
       return <Todo todo={currentTodo} deleteItem={this.deleteItemHandler} key={i} />;
   })
}

3)成功删除项目后使用它

<td>
   {/* this is where the delete happens */}
   <button onClick={ () =>
       axios.delete('http://localhost:4000/todos/'+props.todo._id)
          .then(() => props.deleteItem(props.todo._id))                    
          .catch(err => console.log(err))
    }
    >Delete</button>
</td>

另一种方式

代替从TodosList组件中删除项目,您还可以更新状态。为此,您可以

1)添加在TodosList组件中更新的方法

 updateStateHandler = () => { 
     axios.get('http://localhost:4000/todos/')
        .then(res => {
             this.setState({ todos: res.data });
        })
        .catch(function(err){
            console.log(err);
       })
  }

2)将方法updateStateHandler作为道具传递给Todo组件

todoList() {
    return this.state.todos.map((currentTodo, i) => {
       return <Todo todo={currentTodo} updateState={this.updateStateHandler} key={i} />;
   })
}

3)成功删除项目后使用它

<td>
   {/* this is where the delete happens */}
   <button onClick={ () =>
       axios.delete('http://localhost:4000/todos/'+props.todo._id)
          .then(() => props.updateState())                    
          .catch(err => console.log(err))
    }
    >Delete</button>
</td>

答案 1 :(得分:1)

您需要执行此操作

export default class TodosList extends Component {

    constructor(props) {
        super(props);
        this.state = {todos: []};
        this.fetchTodos = this.fetchTodos.bind(this);
    }

    fetchTodos() {
        axios.get('http://localhost:4000/todos/')
            .then(res => {
                this.setState({ todos: res.data });
            })
            .catch(function(err){
                console.log(err);
            });
    }

    componentDidMount() {
         this.fetchTodos();
    }

    todoList() {
        return this.state.todos.map((currentTodo, i) => {
            return <Todo todo={currentTodo} fetchTodos={this.fetchTodos}  key={i} />;
        })
    }
   ...

Todo:

        <td>
            {/* this is where the delete happens */}
            <button onClick={ () =>
                axios.delete('http://localhost:4000/todos/'+props.todo._id)
                    .then(() => {
                         console.log("Deleted: " + props.todo._id);
                         props.fetchTodos();
                     })                    
                    .catch(err => console.log(err));
            }
            >Delete</button>
        </td>

答案 2 :(得分:0)

呈现表的权限是您的TodosList类,因此需要告知进行删除:

class TodosList extends ... {
  ...
  todoList() {
    return this.state.todos.map((currentTodo, i) => {
      let onDelete = () => {
        this.removeItem(i);
      };
      // NEVER use an array position as key. The key is meant to uniquely
      // identify the _item itself_ and is used in DOM diffing. Moving elements
      // inside an array does not change those elements in the slightest and only
      // requires moving DOM nodes around, but if you use array position as key,
      // what you've now done is said that _everything in the DOM node has changed_
      // So: don't do that. Use a real, item based, value.
      return <Todo todo={currentTodo} key={currentTodo.id} onDelete={onDelete}/>;

      // Of course this assumes todo items have an `id` property.
      // If they don't, pick another property _on the todo item_ that
      // uniquely identifies it.
    });
  }

  removeItem(i) {
    let todos = this.state.todos;
    todos.splice(i,1);
    // This single call now results in all the UI updates that you
    // need to have happen: the todo item is no longer in the state,
    // and so its DOM node will be removed from the page. And because
    // we're now using real keys, React will not touch any of the other
    // DOM nodes. The UI update is near-instant.
    this.setState({ todos });
  }
  ...
}

然后,一旦删除发生,各个按钮便可以调用它们自己的onDelete:

const deleteThisItem = () => {
  axios
  .delete('http://localhost:4000/todos/'+props.todo._id)
  .then(this.props.onDelete())                    
  .catch(err => console.log(err))
};

<button onClick={deleteThisItem}>delete</button>

所以流程是:

  • TodoList知道所有待办事项,
  • TodoList为每个待办事项生成UI,
  • 项目UI包含一个按钮,该按钮将调用 TodoList 的项目删除功能,该功能将更新 TodoList 状态
  • 仅仅通过从该状态中移除一个项目并通过该更改调用setState,React就会呈现需要呈现的内容。