反应this.setState不重新呈现

时间:2019-04-08 15:48:23

标签: reactjs

所以我有这个课:

class TaskList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      tasks: []
    };

    this.handleDelete = this.handleDelete.bind(this);
    this.handleEdit = this.handleEdit.bind(this);
  }

  componentWillMount() {
    axios.get("/api/all").then(result => {
      this.setState({
        tasks: result.data
      });
    });
  }

  handleDelete(id) {
    axios.delete(`/api/${id}`).then(res => {
      axios.get("/api/all").then(tasks => {
        this.setState({
          tasks: tasks.data
        });
      });
    });
  }

  handleEdit(id, updatedTask) {
    axios.put(`/api/${id}`, updatedTask).then(res => {
      axios.get("/api/all").then(tasks => {
        console.log(tasks);
        this.setState({
          tasks: tasks.data
        });
      })
      .catch(err => {
        console.log(err);
      })
    }).catch(err => {
      console.log(err);
    });
  }
  render() {
    const { tasks } = this.state;
    console.log('list render');
    console.log(this.state);
    return (
      <div className="container">
        <div className="title row col-lg-6 mx-auto">
          <div className="col-sm-4">{"Date"}</div>
          <div className="col-sm-4">{"Task"}</div>
          <div className="col-sm-4">{"Status"}</div>
        </div>
        {tasks.map(i => (
          <div className={`${i._id} task mx-auto col-lg-6`}>
            <div className={`${i._id} row`}>
              <Task
                key={i._id}
                id={i._id}
                title={i.title}
                date={i.date}
                complete={i.complete}
                handleDelete={this.handleDelete}
                handleEdit={this.handleEdit}
              />
            </div>
          </div>
        ))}
      </div>
    );
  }
}

任务组件

class Task extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: new Date(props.date),
      complete: props.complete
    };

    this.handleDelete = this.handleDelete.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  handleDelete() {
    this.props.handleDelete(this.props.id);
  }

  handleClick() {
    const updatedTask = {
      title: this.props.title,
      complete: !this.state.complete
    };
    this.setState({ complete: !this.state.complete });
    this.props.handleEdit(this.props.id, updatedTask);
  }

  render() {
    const { title } = this.props;
    const { date, complete} = this.state;
    return (
      <>
        <div className='col-sm-4'>
          {date.getFullYear() + "/" + date.getMonth() + "/" + date.getDate()}
        </div>
        <div className="col-sm-4">{title}</div>
        <div className="col-sm-3" onClick={this.handleClick}><Status complete={complete}/></div>
        <div className="col-sm-1" onClick={this.handleDelete}><IconClose /></div>
      </>
    );
  }
}

状态组件

const Status = props => {
  console.log(props);
  return (
    <>
      {props.complete ? (
        <i className="far fa-check-square" />
      ) : (
        <i className="far fa-square" />
      )}
    </>
  );
};

我遇到的问题是我的handleEdit上的问题,我没有使组件使用更新的任务列表重新呈现。 handleDelete函数可以正常工作并更新屏幕,但不能进行编辑。

我一直以为setState会导致重新渲染,然后我也尝试了forceUpdate,但是它也不起作用。

任何帮助都会很棒。

1 个答案:

答案 0 :(得分:0)

我认为这里的问题是道具进入国家的分支。

Task内部,代码调用this.props.handleEdit(this.props.id, updatedTask),它将数据发送到父组件TaskList。该handleEdit函数更新了tasks的状态键TaskList

但是,当每个任务的完成状态传递给Task时,它从props分支到其自己的组件状态:

this.state = {
  ...
  complete: props.complete
};

constructor函数仅被调用一次; props.complete再也无法更新状态。我的建议是使用从TaskList传递过来的道具,除非出于特殊原因必须将其完整性值存储在Task内。

React文档解释了这种常见的反模式:

  

问题在于,这既不必要(您可以直接使用this.props.color),又会产生错误(对颜色道具的更新不会反映在状态中)。

     

仅当您有意忽略道具更新时才使用此模式。

React constructor docs