使用下拉列表更改状态后,不重新渲染React组件[react hooks]

时间:2019-09-11 08:10:26

标签: reactjs react-hooks use-effect

我有以下React组件(使用hooks),它列出了多个Tasks作为下拉列表。从列表中选择一个项目后,我要显示一个Update表单。仅当第一次选择一个项目时,此功能才有效。当我选择一个新项目时,什么也没发生(尽管console.log(e.target.value);打印正确的值)。我将所选任务的ID存储在st_taskId中。

我想知道您是否在下面的代码中看到任何问题:

const ManageReviewTasks = props => {
  const reviewRoundId = props.match.params.reviewRoundId;
  const [st_taskId, set_taskId] = useState();

  useEffect(() => {
    if (props.loading == false && st_taskId == null)
      props.fetchReviewTasksByReviewRound(reviewRoundId);
  }, [reviewRoundId, st_taskId]);

  if (props.loading == true) {
    return <div>Loading...</div>;
  }

  return (
    <>
      {props.reviewTasks && (
        <div>
          <h3>Configure the Review Tasks</h3>
          <br />
          {
            <div>
              <div>
                <h4>
                  Tasks for <span className="font-italic">students receiving</span> feedback:
                </h4>
                <select
                  className="form-control"
                  onChange={e => {
                    e.preventDefault();
                    console.log(e.target.value);
                    set_taskId(e.target.value);
                  }}>
                  <option>--SELECT--</option>
                  {Object.keys(props.reviewTasks).map(id => {
                    const task = props.reviewTasks[id];
                    {
                      if (task.isForStudent) {
                        return (
                          <option key={id} id={id} value={id}>
                            {task.title}
                          </option>
                        );
                      }
                    }
                  })}
                </select>
              </div>
              {props.reviewTasks[st_taskId] && (
                <UpdateReviewTaskForm task={props.reviewTasks[st_taskId]} />
              )}
            </div>
          }
        </div>
      )}
    </>
  );
};

下面是UpdateReviewTaskForm组件的代码:

const UpdateReviewTaskForm = (props) => {

    const [st_Title, set_Title] = useState(props.task.title);
    const [st_Description, set_Description] = useState(RichTextEditor.createValueFromString(props.task.description, 'html'));
    const [st_startDate, set_startDate] = useState(new Date(props.task.startDate.replace('-', '/')));
    const [st_DueDate, set_DueDate] = useState(new Date(props.task.dueDate.replace('-', '/')));



    const handleCancelClick = (event) => {
        event.preventDefault();
        history.goBack();
    }

    const onSubmit_saveTask = (e) => {
        e.preventDefault();

        props.updateReviewTask({
            Id: props.task.id,
            Title: st_Title,
            Description: st_Description.toString('html'),
            StartDate: format(st_startDate, 'DD/MM/YYYY'),
            DueDate: format(st_DueDate, 'DD/MM/YYYY'),
        })
    }

    if (props.loading) 
        return <div>Updating...</div>

    return (
        <div>
            <br/>
            <br/>
            <div className="p-3 bg-light">
                <h3 className="text-info">Update the Task:</h3>
                {
                    props.task &&
                    <form onSubmit={onSubmit_saveTask}>
                        <div className="form-group">
                            <label>Enter the title</label>
                            <input
                                //placeholder="Enter a title..."
                                value={st_Title}
                                onChange={(event) => { set_Title(event.target.value) }}
                                className="form-control" />
                        </div>

                        <div className="form-group">
                            <label>Enter a description for the assessment</label>
                            <RichTextEditor
                                value={st_Description}
                                onChange={set_Description}
                            />
                        </div>

                        <div className="form-group">
                            <label>Start date to start:&nbsp;</label>
                            <DatePicker
                                className="form-control"
                                selected={st_startDate}
                                onChange={(date) => set_startDate(date)}
                            />
                        </div>
                        <div className="form-group">
                            <label>Due date to complete:&nbsp;</label>
                            <DatePicker
                                className="form-control"
                                selected={st_DueDate}
                                onChange={(date) => set_DueDate(date)}
                            />
                        </div>

                        <br />
                        <button type="submit" className="btn btn-primary">Submit</button>&nbsp;
                        <button type="reset" className="btn btn-light" onClick={handleCancelClick}>Cancel</button>
                    </form>
                }
            </div>
        </div>
    )
}

1 个答案:

答案 0 :(得分:1)

由于您正在UpdateReviewTaskForm中使用内部状态,即使该组件第二次重新渲染,其状态也不会重置(例如,恢复为默认值props.task.title)。

强制重置状态的一种方法是在key中使用UpdateReviewTaskForm道具,如下所示:

  {props.reviewTasks[st_taskId] && (
    <UpdateReviewTaskForm key={st_taskId} task={props.reviewTasks[st_taskId]} />
  )}

另一种方法是在useEffect更改时在UpdateReviewTaskForm内使用props.task运行

useEffect(() => {
// reset the state here
}, [props.task])