当 React 已经在渲染时无法刷新更新 [英] Cannot flush updates when React is already rendering

查看:247
本文介绍了当 React 已经在渲染时无法刷新更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

自从我添加了下面的行后,我不断收到错误消息:

{saveLabelFetchError &&this.toggleAlertFailure(saveLabelFetchError)}

错误:

<块引用>

index.js:1375 警告:unstable_flushDiscreteUpdates:无法刷新更新当 React 已经在渲染时.

我的组件:

import React, { Component } from "react";从prop-types"导入 PropTypes;从react-redux"导入{连接};从redux"导入 { bindActionCreators };import { saveLabelValueRequest } from "../../actions/labels";从sweetalert2"导入 Swal;导入./styles.css";从@kof/button"导入按钮;导出类 NewLabels 扩展组件 {状态 = {标签输入:"};inputChangedhandler = e =>{this.setState({ labelInput: e.target.value });};toggleAlertFailure = 消息 =>{Swal.fire({类型:错误",title: "哎呀...",文字:讯息});};saveLabel = 事件 =>{event.persist();event.preventDefault();Swal.fire({标题:你确定吗?",text: "您将无法还原此内容!",类型:警告",显示取消按钮:真,确认按钮颜色:#3085d6",取消按钮颜色:#d33",确认按钮文本:是的,保存它."}).那么(结果=> {如果(结果.值){const labelKeyUuid = this.props.labelKey.uuid;const 标签 = event.target.elements.labels.value;this.props.saveLabelValue(labelKeyUuid, labels);}});};使成为() {const { 加载,saveLabelFetchError } = this.props;返回 (<div><form onSubmit={this.saveLabel}><textarea onChange={this.inputChangedhandler}></textarea><textarea></textarea><Button onClick={() =>load(this.state.labelInput)}>预览</Button><Button type="submit">保存</Button></表单>{saveLabelFetchError &&this.toggleAlertFailure(saveLabelFetchError)}

);}}NewLabels.propTypes = {saveLabelFetchError: PropTypes.string,isFetching: PropTypes.bool,labelKey:PropTypes.object,saveLabelValue: PropTypes.func};NewLabels.defaultProps = {saveLabelFetchError: "",标签键:{},isFetching:假,saveLabelValue: () =>{}};导出默认连接(状态 =>({saveLabelFetchError: state.labelsStore.saveLabelError,isFetching: state.labelsStore.isFetching,labelKey:state.labelsStore.labelKey}),调度 =>绑定动作创建者({saveLabelValue:saveLabelValueRequest},派遣))(NewLabels);

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

解决方案

{saveLabelFetchError &&this.toggleAlertFailure(saveLabelFetchError)}

您正在尝试在渲染周期之前更新 dom,即在组件安装之前.因此,您将收到错误消息.

理想情况下,您应该避免使用任何直接改变 dom 的库(而不是通过 react API)和 react lib.您可以从此处

阅读更多信息

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

<预><代码>import React, { Component } from "react";从prop-types"导入 PropTypes;从react-redux"导入{连接};从redux"导入 { bindActionCreators };import { saveLabelValueRequest } from "../../actions/labels";从sweetalert2"导入 Swal;导入./styles.css";从@kof/button"导入按钮;导出类 NewLabels 扩展组件 {状态 = {标签输入:"",prevSaveLabelFetchError: ""};静态 getDerivedStateFromProps(props, state) {if (props.saveLabelFetchError !== state.prevSaveLabelFetchError) {this.toggleAlertFailure(props.saveLabelFetchError);返回 {prevSaveLabelFetchError: props.saveLabelFetchError};}返回空;}inputChangedhandler = e =>{this.setState({ labelInput: e.target.value });};toggleAlertFailure = 消息 =>{Swal.fire({类型:错误",title: "哎呀...",文字:讯息});};saveLabel = 事件 =>{event.persist();event.preventDefault();Swal.fire({标题:你确定吗?",text: "您将无法还原此内容!",类型:警告",显示取消按钮:真,确认按钮颜色:#3085d6",取消按钮颜色:#d33",确认按钮文本:是的,保存它."}).那么(结果=> {如果(结果.值){const labelKeyUuid = this.props.labelKey.uuid;const 标签 = event.target.elements.labels.value;this.props.saveLabelValue(labelKeyUuid, labels);}});};使成为() {const { 负载} = this.props;返回 (<div><form onSubmit={this.saveLabel}><textarea onChange={this.inputChangedhandler}></textarea><textarea></textarea><Button onClick={() =>load(this.state.labelInput)}>预览</Button><Button type="submit">保存</Button></表单>

);}}NewLabels.propTypes = {saveLabelFetchError: PropTypes.string,isFetching: PropTypes.bool,labelKey:PropTypes.object,saveLabelValue: PropTypes.func};NewLabels.defaultProps = {saveLabelFetchError: "",标签键:{},isFetching:假,saveLabelValue: () =>{}};导出默认连接(状态 =>({saveLabelFetchError: state.labelsStore.saveLabelError,isFetching: state.labelsStore.isFetching,labelKey:state.labelsStore.labelKey}),调度 =>绑定动作创建者({saveLabelValue:saveLabelValueRequest},派遣))(新标签);

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

I'm trying to show an alert when the API returns an error. For the alert window I'm using sweetalert2. In my render method I'm checking if the error message contains content. If it contains an error message I want to show the user an alert.

When I submit the form, I make an API call. If it returns an error the reducer changes the store (state) and it renders the page again.

Since I added the line below, I keep getting an error:

{saveLabelFetchError && this.toggleAlertFailure(saveLabelFetchError)}

error:

index.js:1375 Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.

My component:

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);

I would like to know why i keep getting this error message in my console.

解决方案

{saveLabelFetchError && this.toggleAlertFailure(saveLabelFetchError)}

You are trying to update the dom before render cycle i.e before component has mounted. hence, you are getting an error.

Ideally, you should avoid using any library that mutates dom directly (not via react APIs) with react lib. You can read more from here

The solution is to check if there is a change in props value, if so then show error popup. And also make sure we are not mutating dom during react's render cycle.


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);


You can also look at react wrapper for sweetalert2

这篇关于当 React 已经在渲染时无法刷新更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆