从 redux 操作重置表单状态

Reset form state from redux action

我目前有以下组件,为简单起见,我在 codesandbox here 上创建了一个最小示例。它证明了我的问题。

对于 Whosebug,这里有一些片段:

class CommentForm extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      comment: ""
    };

    this.handleCommentChange = this.handleCommentChange.bind(this);
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  handleCommentChange(evt) {
    this.setState({ comment: evt.target.value });
  }

  handleFormSubmit(evt) {
    evt.preventDefault();
    this.props.addComment(this.state.comment);
  }
  render() {
    const { submitting } = this.props;

    return (
      <form onSubmit={this.handleFormSubmit}>
          <textarea
            name="comment"
            placeholder="Write your comment here..."
            rows="5"
            value={this.state.comments}
            onChange={this.handleCommentChange}
          />
          <br />
          <input
            type="submit"
            disabled={submitting}
            value="COMMENT"
          />
      </form>
    );
  }
}

我的问题:当我的 saga 调度动作 COMMENT_ADD_SUCCESS 时,如何重置表单状态 (this.state.comments = '')?

我想避免的事情:在 redux 状态下添加评论。我知道我可以将评论移动到 redux 存储中,并且 return 类似于 {...state, commentField: ''} 的东西在 reducer 本身中。

为了演示目的,这个表单很简单,但我有一个复杂得多的表单,我觉得不需要将其添加到 redux 存储中,因为它的状态是短暂的,一旦组件死亡,状态可以简单地被丢弃。此外,如果我需要向商店添加评论,我需要创建像 COMMENT_UPDATED 这样的操作来更新 redux 商店,这可能是一个相当大的麻烦,尤其是对于具有很多字段的表单。

你能做这样的事情吗?

  handleFormSubmit(evt) {
    evt.preventDefault();
    this.props.addComment(this.state.comment);
    this.setState({ comments: ''});
  }

扩展@Lefi 所说的内容:

您可以添加回调并在您的 saga.js 中调用它。

callback = () => {
  this.setState({ comments : '' })
}

handleFormSubmit(comment, callback) {
  ...
}

下面的代码应该可以工作,因为您提供了 submitting 道具。你想要做的是捕捉从真到假的转变。

  componentDidUpdate( prevProps ) {
    
    if ( prevProps.submitting === this.props.submitting ) {
      // The state of our comment submission hasn't changed so do nothing.
      return;
    }

    if ( ! this.props.submitting ) {
      // The comment just finished submitting because we
      // we went from true to false
      this.setState( { comments: '' } );
    }

    
  }

我通常将回调作为额外参数传递给操作,并从传奇中调用回调。因此,我将更改您的 CommentForm 代码以分派传递具有文本值和回调函数的对象的操作:

handleFormSubmit(evt) {
    evt.preventDefault();
    this.props.addComment({ comment: this.state.comment, callback: function() {
      alert("callback invoked");
      // here do cleanup of state as you wish
    }});
  }

并更改 saga 以在成功时调用回调:

function* addComment(params) {
  console.log("Adding Comment");

  yield put({ type: "ADD_COMMENT_FETCHING" });

  // Simulate call success
  yield call(delay, 5000);

  alert("(From saga) The comment was added successfully.");
  yield put({ type: "ADD_COMMENT_SUCCESS" });

  params.action.callback(); // <--- here the callback
}

Redux 状态未受影响,您还可以考虑添加第二个回调,在 saga 中 failure/error 时将调用该回调。 我fork了你的sandbox,你可以查看代码here