当 React 已经呈现时无法刷新更新

新手上路,请多包涵

我试图在 API 返回错误时显示警报。对于警报窗口,我使用的是 sweetalert2。在我的渲染方法中,我正在检查错误消息是否包含内容。如果它包含一条错误消息,我想向用户显示一个警报。

当我提交表单时,我会调用 API。如果返回错误,reducer 会更改存储(状态)并再次呈现页面。

由于我添加了下面的行,我不断收到错误消息:

 {saveLabelFetchError && this.toggleAlertFailure(saveLabelFetchError)}

错误:

index.js:1375 警告:unstable_flushDiscreteUpdates:当 React 已经呈现时无法刷新更新。

我的组件:

 import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";

import { saveLabelValueRequest } from "../../actions/labels";

import Swal from "sweetalert2";
import "./styles.css";
import Button from "@kof/button";

export class NewLabels extends Component {
  state = {
    labelInput: ""
  };

  inputChangedhandler = e => {
    this.setState({ labelInput: e.target.value });
  };

  toggleAlertFailure = message => {
    Swal.fire({
      type: "error",
      title: "Oops...",
      text: message
    });
  };

  saveLabel = event => {
    event.persist();
    event.preventDefault();
    Swal.fire({
      title: "Are you sure?",
      text: "You won't be able to revert this!",
      type: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "Yes, save it."
    }).then(result => {
      if (result.value) {
        const labelKeyUuid = this.props.labelKey.uuid;
        const labels = event.target.elements.labels.value;
        this.props.saveLabelValue(labelKeyUuid, labels);
      }
    });
  };

  render() {
    const { load, saveLabelFetchError } = this.props;
    return (
      <div>
        <form onSubmit={this.saveLabel}>
          <textarea onChange={this.inputChangedhandler}></textarea>
          <textarea></textarea>
          <Button onClick={() => load(this.state.labelInput)}>Preview</Button>
          <Button type="submit">Save</Button>
        </form>
        {saveLabelFetchError && this.toggleAlertFailure(saveLabelFetchError)}
      </div>
    );
  }
}

NewLabels.propTypes = {
  saveLabelFetchError: PropTypes.string,
  isFetching: PropTypes.bool,
  labelKey: PropTypes.object,
  saveLabelValue: PropTypes.func
};

NewLabels.defaultProps = {
  saveLabelFetchError: "",
  labelKey: {},
  isFetching: false,
  saveLabelValue: () => {}
};

export default connect(
  state => ({
    saveLabelFetchError: state.labelsStore.saveLabelError,
    isFetching: state.labelsStore.isFetching,
    labelKey: state.labelsStore.labelKey
  }),
  dispatch =>
    bindActionCreators(
      {
        saveLabelValue: saveLabelValueRequest
      },
      dispatch
    )
)(NewLabels);

我想知道为什么我不断在我的控制台中收到此错误消息。

原文由 J. Adam 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 939
1 个回答
{saveLabelFetchError && this.toggleAlertFailure(saveLabelFetchError)}

您正在尝试在渲染周期之前更新 dom,即在组件安装之前。因此,您遇到了错误。

理想情况下,您应该避免使用任何直接改变 dom 的库(不是通过 react API)和 react lib。你可以从 这里 阅读更多

解决方案是检查 props 值是否有变化,如果有则显示错误弹出窗口。还要确保我们不会在 React 的渲染周期中改变 dom。


import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";

import { saveLabelValueRequest } from "../../actions/labels";

import Swal from "sweetalert2";
import "./styles.css";
import Button from "@kof/button";

export class NewLabels extends Component {
  state = {
    labelInput: "",
    prevSaveLabelFetchError: ""
  };

  static getDerivedStateFromProps(props, state) {
    if (props.saveLabelFetchError !== state.prevSaveLabelFetchError) {
      this.toggleAlertFailure(props.saveLabelFetchError);
      return {
        prevSaveLabelFetchError: props.saveLabelFetchError
      };
    }
    return null;
  }

  inputChangedhandler = e => {
    this.setState({ labelInput: e.target.value });
  };

  toggleAlertFailure = message => {
    Swal.fire({
      type: "error",
      title: "Oops...",
      text: message
    });
  };

  saveLabel = event => {
    event.persist();
    event.preventDefault();
    Swal.fire({
      title: "Are you sure?",
      text: "You won't be able to revert this!",
      type: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "Yes, save it."
    }).then(result => {
      if (result.value) {
        const labelKeyUuid = this.props.labelKey.uuid;
        const labels = event.target.elements.labels.value;
        this.props.saveLabelValue(labelKeyUuid, labels);
      }
    });
  };

  render() {
    const { load } = this.props;
    return (
      <div>
        <form onSubmit={this.saveLabel}>
          <textarea onChange={this.inputChangedhandler}></textarea>
          <textarea></textarea>
          <Button onClick={() => load(this.state.labelInput)}>Preview</Button>
          <Button type="submit">Save</Button>
        </form>
      </div>
    );
  }
}

NewLabels.propTypes = {
  saveLabelFetchError: PropTypes.string,
  isFetching: PropTypes.bool,
  labelKey: PropTypes.object,
  saveLabelValue: PropTypes.func
};

NewLabels.defaultProps = {
  saveLabelFetchError: "",
  labelKey: {},
  isFetching: false,
  saveLabelValue: () => {}
};

export default connect(
  state => ({
    saveLabelFetchError: state.labelsStore.saveLabelError,
    isFetching: state.labelsStore.isFetching,
    labelKey: state.labelsStore.labelKey
  }),
  dispatch =>
    bindActionCreators(
      {
        saveLabelValue: saveLabelValueRequest
      },
      dispatch
    )
)(NewLabels);

您还可以查看 sweetalert2 的反应包装器

原文由 Abhishek 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题