ReactJS 状态更新落后一步

时间:2021-01-03 06:59:12

标签: reactjs axios jsx

我正在尝试使用 ReactJS 创建一个简单的表格来显示用户信息。下面是一般代码结构的样子:

class ParentComponent extends React.Component {
  state = { 
    data : [] 
  }

  componentDidMount() {
    // initializes state with data from db
    axios.get("link/").then(res => {
      this.setState({data: res.data});
    });

    // I should be able to call this.getData() instead
    // of rewriting the axios.get() function but if I do so,
    // my data will not show up

  }
  
  // retrieves array of data from db
  getData = () => {
    axios.get("link/").then(res => {
      this.setState({data: res.data});
    });
  }  

  render() {
    return (
      <div>
        <ChildComponent data={this.state.data} refetch={this.getData} />
      </div>
    )
  }
}

每个生成的行都应该有一个删除函数,我将根据给定的 id 从数据库中删除条目。删除后想从父组件中取回最新的数据重新显示。

class ChildComponent extends React.Component {

  // deletes the specified entry from database
  deleteData = (id) => {
    axios.get("deleteLink/" + id).then(res => {
      console.log(res);
      // calls function from parent component to 
      // re-fetch the latest data from db
      this.props.refetch();

    }).catch(err => {console.log(err)});
  }

  render() {
    let rows = null;
    if(this.props.data.length) {
      // map the array into individual rows
      rows = this.props.data.map(x => {
        return (
          <tr>
            <td>{x.id}</td>
            <td>{x.name}</td>
            <td>
               <button onClick={() => {
                 this.deleteData(x.id)
                }}>
                  Delete
               </button>
            </td>
          </tr>
        )
      })

    }

    return (
      <div>
        <table>
          <thead></thead>
          <tbody>
            {rows}
          </tbody>
        </table>
      </div>
    )
  }
}

我在这里遇到的两个问题是:

  1. 从逻辑上讲,我应该能够从 componentDidMount() 中调用 this.getData(),但如果我这样做,表不会加载。
  2. 每当我尝试删除一行时,即使该条目已从数据库中删除,该表也不会反映更新。表格只会在我刷新页面或删除另一行时更新。问题是,该组件总是落后 1 个更新。

到目前为止我已经尝试过:

  1. this.forceUpdate() - 不起作用
  2. this.setState({}) - 空的 setState 也不起作用
  3. componentDidMount() 更改为 componentDidUpdate() - 错误显示我已“达到最大深度”或沿该线的某些内容
  4. 在 axios 前面添加异步等待 - 不起作用

感谢任何帮助。提前致谢。


编辑:我进行了一些调试并找到了与我的问题无关的问题。我位于 ChildComponent 中的 deleteData() 使用 axios.post() 而不是 axios.get(),这是我忽略的。

deleteData = (id) => {
    axios.post("deleteLink/", id).then(res => {
      console.log(res);
      // calls function from parent component to 
      // re-fetch the latest data from db
      this.props.refetch();

    }).catch(err => {console.log(err)});
  }

为了让 axios.post() 返回响应,为了执行 .then(),您需要在路由代码中添加一个 res.json()

2 个答案:

答案 0 :(得分:3)

您应该将数据映射到您的孩子身上。

像这样改变你的父母:

class ParentComponent extends React.Component {
  state = { 
      data : [] 
  }

  componentDidMount() {
      this.getData();
  }
    
  getData = () => axios.get("link/").then(res => this.setState({data: res.data});
    
  deleteData = (id) => axios.get("deleteLink/" + id).then(res => this.getData())
       .catch(err => { console.log(err) });

  render() {
    return (
      <div>
        <table>
          <thead></thead>
          <tbody>
            {this.state.data.map(x => <ChildComponent row={x} deleteData={this.deleteData} />)}
          </tbody>
        </table>
      </div>
    )
  }
}

你的子组件应该是这样的

const ChildComponent = ({row,deleteData}) => (
      <tr>
        <td>{row.id}</td>
        <td>{row.name}</td>
        <td><button onClick={() => deleteData(row.id)}>Delete</button></td>
      </tr >
    )

答案 1 :(得分:1)

我在您的代码中找不到问题,我能提供帮助的唯一方法就是告诉您我将如何调试它。

像这样编辑父级:

class ParentComponent extends React.Component {
  state = { 
    data : [] 
  }

  componentDidMount() {
    // You are right when you say this should works, so 
    // stick to it until the bug is fixed
    
    console.log("parent mounted");
    this.getData();
  }
  
  // retrieves array of data from db
  getData = () => {
    console.log("fetching data");

    axios.get("link/").then(res => {
      console.log("fetched data", res.data);
      this.setState({data: res.data});
    });
  }  

  render() {
    return (
      <div>
        <ChildComponent 
          data={this.state.data}
          refetch={this.getData}
        />
      </div>
    )
  }
}

在子组件中添加这两个生命周期方法只是为了调试:

componentDidMount () {
   console.log("child mounted", this.props.data)     
}

componentDidUpdate (prevProps) {
   console.log("old data", prevProps.data);
   console.log("new data", this.props.data);
   console.log("data are equal", prevProps.data === this.props.data);
}

如果您可以共享日志,我可以尝试为您提供更多帮助