【问题标题】:Cannot flush updates when React is already renderingReact 已经在渲染时无法刷新更新
【发布时间】:2020-01-22 06:02:37
【问题描述】:

我正在尝试在 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);

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

【问题讨论】:

  • 同样的问题。我得到它的代码没有改变。想知道这是否是由于 React 更新造成的。
  • 我在更新 react 后也开始得到这个。还使用了 Sweet Alert,所以我认为这是 Sweet Alert 中的某处。
  • 和sweet包有关。

标签: javascript reactjs sweetalert


【解决方案1】:
{saveLabelFetchError && this.toggleAlertFailure(saveLabelFetchError)}

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

理想情况下,您应该避免将任何直接变异 dom 的库(不是通过 react API)与 react lib 一起使用。你可以从here阅读更多内容

解决方法是检查 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);


你也可以看看react wrapper for sweetalert2

【讨论】:

    【解决方案2】:

    试试这个代码 sn-p:

    const [state, setState] = useState(true)
    
    const renderFunc = () => {
        ...
        setState(false)
    }
    
    state && renderFunc()
    

    【讨论】:

      猜你喜欢
      • 2020-04-06
      • 2022-01-04
      • 2020-01-27
      • 1970-01-01
      • 2016-12-11
      • 2016-12-30
      • 2019-12-27
      • 2018-05-01
      • 1970-01-01
      相关资源
      最近更新 更多