简体   繁体   English

在AJAX请求之后重新渲染React组件

[英]Re-Render React Component After AJAX Request

I'm building a CRUD application with React and I wondered if you could help on this issue. 我正在用React构建一个CRUD应用程序,我想知道你是否可以在这个问题上提供帮助。

I am making a AJAX GET request with componentDidMount to the server which retrieves the data and then sets the state in the success function. 我正在向服务器发出一个带有componentDidMount的AJAX GET请求,该服务器检索数据,然后在success函数中设置状态。 In the render function I then map over the state array and render each state into a <li> element and include a <button> element. 在渲染函数中,然后映射state数组并将每个状态渲染为<li>元素并包含<button>元素。

When the <button> element is clicked it calls the delete() function. 单击<button>元素时,它将调用delete()函数。 This then calls the AJAX DELETE request on the ID. 然后,它会在ID上调用AJAX DELETE请求。

My problem is how do I get the component to re-render or update the state after the AJAX request is a success? 我的问题是如何在AJAX请求成功后让组件重新呈现或更新状态?

import React from 'react';

class PostList extends React.Component {
  constructor() {
    super();
    this.state = {
      posts: []
    }
  }

  componentDidMount() {
    $.ajax({
       url: '/posts',
       type: "GET",
       dataType: 'json',
       cache: false,
       success: function(data) {
         this.setState({posts: data})
       }.bind(this)
    });
  }

  delete(event) {
    let postId = event.target.parentNode.getAttribute("data-id");
      $.ajax({
         url: '/posts/' + postId,
         type: "DELETE",
         success: function(data) {
          console.log(data);
         }.bind(this)
      });
  }

  render() {
    let posts = this.state.posts.map( (index) => {
      return <li data-id={index._id} className="list-group-item"><a href={"posts/" + index._id}>{index.title}</a><button className="btn btn-default" onClick={this.delete.bind(this)}>Delete</button></li>
    })
    return (
      <ul className="list-group">
        {posts}
      </ul>
    )
  }
}

export default PostList;

Update the state in the delete handler. delete处理程序中更新状态。

You've got two options: 你有两个选择:

  1. optimistic, it instantly updates the UI, however, the request could fail and you need to handle this case. 乐观,它会立即更新UI,但是,请求可能会失败,您需要处理这种情况。

     delete(event) { let postId = event.target.parentNode.getAttribute("data-id"); this.setState({ posts: this.state.posts.filter(post => post._id !== postId) }) $.ajax({ url: '/posts/' + postId, type: "DELETE" }); } 
  2. pessimistic, will only mutate the state with a successful request, but could take a while before the UI is updated. 悲观,只会通过成功请求改变状态,但可能需要一段时间才能更新UI。

     delete(postId) { $.ajax({ url: '/posts/' + postId, type: "DELETE", success: function(data) { this.setState({ posts: this.state.posts.filter(post => post._id !== postId) }) }.bind(this) }); } 

For handling state, you could dive into state management libraries like Redux . 对于处理状态,您可以深入了解Redux等状态管理库。

I dont know how the rest of your app works, but I guess your code is a module of something "bigger". 我不知道你的应用程序的其余部分是如何工作的,但我猜你的代码是一个“更大”的模块。 Since you use es2015 syntax I think you can achive what you want like this. 由于你使用es2015语法,我认为你可以像这样得到你想要的东西。

What you want is to update the state on your <MyApp /> or what ever you have. 您想要的是更新<MyApp />上的状态或您拥有的状态。 And then you pass the state as a prop and the function that will update the state of your <MyApp /> like this <PostList posts={this.state.posts} onDelete={this.onDelete()}/> 然后你将状态作为prop传递,并且将更新<MyApp />状态的函数,如此<PostList posts={this.state.posts} onDelete={this.onDelete()}/>

class MyApp extends React.Component {
constructor() {
  super();
  this.state = {
    posts: []
  }
}

onDelete(data){
  this.setState({posts: data})
}

render(){
  return (    
    <div>
      <PostList posts={this.state.posts} onDelete={this.onDelete()}/> 
    </div>
  )}
}

Here you change your onClick to (e)=> this.delete(e) (if you use fat arrow functions you do not need to bind this anymore. 在这里你将onClick更改为(e)=> this.delete(e) (如果使用胖箭头函数,则不需要再绑定它。

In your delete function you can now call onDelete(data) that is in your <MyApp /> with the data. 在您的删除功能中,您现在可以使用onDelete(data)调用<MyApp /> onDelete(data) This will make your app re-render everyhitng. 这将使您的应用重新渲染每个人。

import React from 'react';

        class PostList extends React.Component {
          constructor() {
    super();
    this.state = {
      posts: []
    }
  }

  componentDidMount() {
    $.ajax({
       url: '/posts',
       type: "GET",
       dataType: 'json',
       cache: false,
       success: function(data) {
         this.setState({posts: data})
       }.bind(this)
    });
  }

  delete(event) {
    let postId = event.target.parentNode.getAttribute("data-id");
    let data;
      $.ajax({
         url: '/posts/' + postId,
         type: "DELETE",
         success: function(_d) {
          data = _d;
         }.bind(this)
      });
      onDelete(data);
  }

  render() {
    let posts = this.props.posts.map( (index) => {
      return <li data-id={index._id} className="list-group-item"><a href={"posts/" + index._id}>{index.title}</a><button className="btn btn-default" onClick={(e)=> this.delete(e)}>Delete</button></li>
    })
    return (
      <ul className="list-group">
        {posts}
      </ul>
    )
  }
}

export default PostList;

Good luck! 祝好运!

You can force update using the component's forceUpdate() method. 您可以使用组件的forceUpdate()方法强制更新。 That will ensure you re-render. 这将确保您重新渲染。 However, it'd be better if you responded to whatever that call returned by setting the state, which will also re-render. 但是,如果您通过设置状态响应所返回的任何内容会更好,这也将重新呈现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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