Skip to content Skip to sidebar Skip to footer

Cannot Flush Updates When React Is Already Rendering

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

Solution 1:

{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


Solution 2:

Try this code snippet:

const [state, setState] = useState(true)

const renderFunc = () => {
    ...
    setState(false)
}

state && renderFunc()

Post a Comment for "Cannot Flush Updates When React Is Already Rendering"