Как мое приложение может обнаружить какие-либо изменения redux, чтобы вызвать прослушиватель событий «beforeunload»? - PullRequest
0 голосов
/ 05 августа 2020

Я создаю базовое c приложение с длинной формой.

Форма управляется с помощью redux и меняет состояние redux на входе с помощью метода onChange. Вот мой компонент формы:

import React, { Component } from "react";

import { connect } from "react-redux";
import { setCard } from "../../store/actions/card";

import "../../constants/colors.css";
import "./UI.css";

class CardForm extends Component {
  constructor(props) {
    super(props);

    this.state = {
      id: props.card.id,
      businessName: props.card.businessName,
      businessIndustry: props.card.businessIndustry,
      businessServices: props.card.businessServices,
      businessPhoneNumber: props.card.businessPhoneNumber,
      businessEmail: props.card.businessEmail,
    };
  }

  handleImageSelectorClick = () => {};

  cardFormInputChangeHandler = async (event) => {
    await this.setState({
      [event.target.name]: event.target.value,
    });

    const businessNameValue = this.state.businessName;
    const businessIndustryValue = this.state.businessIndustry;
    const businessServicesValue = this.state.businessServices;
    const businessPhoneNumberValue = this.state.businessPhoneNumber;
    const businessEmailValue = this.state.businessEmail;

    this.props.setCard(
      this.state.id,
      businessNameValue,
      businessIndustryValue,
      businessServicesValue,
      businessPhoneNumberValue,
      businessEmailValue
    );
  };

  render() {
    return (
      <div className="primary-light-bg card-form-wrapper">
        <div className="card-form-container">
          <div
            className="primary-color-bg card-form-business-img"
            onClick={this.handleImageSelectorClick}
          ></div>
          <input
            className="card-form-input"
            name="businessName"
            placeholder="Business Name"
            value={this.state.businessName}
            onChange={this.cardFormInputChangeHandler}
          />
          <div className="card-form-dropdown-container">
            <select
              className="card-form-dropdown"
              name="businessIndustry"
              defaultValue={
                this.state.businessIndustry === ""
                  ? "DEFAULT"
                  : this.state.businessIndustry
              }
              onChange={this.cardFormInputChangeHandler}
            >
              <option value="DEFAULT" disabled>
                Select a Business Industry
              </option>
              <option value="Software Development">Software Development</option>
              <option value="Clothing and Apparel">Clothing and Apparel</option>
              <option value="Health and Beauty">Health and Beauty</option>
            </select>
          </div>
          <textarea
            className="card-form-input-large"
            name="businessServices"
            placeholder="Business Services"
            value={this.state.businessServices}
            onChange={this.cardFormInputChangeHandler}
          />
          <div className="card-form-contact-fields">
            <input
              id="cardFormInputPhoneNumber"
              className="card-form-input-contact"
              name="businessPhoneNumber"
              placeholder="Phone Number"
              value={this.state.businessPhoneNumber}
              onChange={this.cardFormInputChangeHandler}
            />
            <input
              id="cardFormInputEmail"
              className="card-form-input-contact"
              name="businessEmail"
              placeholder="Email"
              value={this.state.businessEmail}
              onChange={this.cardFormInputChangeHandler}
            />
          </div>
          <div
            className="card-form-button"
            onClick={() => this.props.toggleModal()}
          >
            <span className="primary-color card-form-button-text">
              + Add Social Media
            </span>
          </div>
        </div>
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    card: state.card,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    setCard: (
      id,
      businessName,
      businessIndustry,
      businessServices,
      businessPhoneNumber,
      businessEmail
    ) =>
      dispatch(
        setCard(
          id,
          businessName,
          businessIndustry,
          businessServices,
          businessPhoneNumber,
          businessEmail
        )
      ),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(CardForm);

Это мой редуктор и действие для моей формы:

cardActions. js

import { IS_LOADING, IS_NOT_LOADING } from "./loader";

export const FETCH_CARD = "FETCH_CARD";
export const SET_CARD = "SET_CARD";

export const fetchCard = () => {
  return (dispatch) => {
    dispatch({ type: IS_LOADING });
    fetch(`http://localhost:4000/cards/1`)
      .then((resp) => resp.json())
      .then((card) => {
        dispatch({ type: SET_CARD, card: card });
        localStorage.setItem("card", JSON.stringify(card));
        dispatch({ type: IS_NOT_LOADING });
      });
  };
};

export const setCard = (
  id,
  businessName,
  businessIndustry,
  businessServices,
  businessPhoneNumber,
  businessEmail
) => {
  return {
    type: SET_CARD,
    card: {
      id,
      businessName,
      businessIndustry,
      businessServices,
      businessPhoneNumber,
      businessEmail,
    },
  };
};

Каждый раз, когда информация о карте извлекается из моего API, я сохраняю объект карты в localStorage, чтобы получить чистую копию самой последней информации о карте.

cardReducer. js

import { SET_CARD } from "../actions/card";

const initialState = {
  id: null,
  businessName: "",
  businessIndustry: "",
  businessServices: "",
  businessPhoneNumber: "",
  businessEmail: "",
};

const loader = (state = initialState, action) => {
  switch (action.type) {
    case SET_CARD:
      return {
        id: action.card.id,
        businessName: action.card.businessName,
        businessIndustry: action.card.businessIndustry,
        businessServices: action.card.businessServices,
        businessPhoneNumber: action.card.businessPhoneNumber,
        businessEmail: action.card.businessEmail,
      };

    default:
      return state;
  }
};

export default loader;

В моем Приложение. js, я сравниваю карту localStorage с моим текущим состоянием редукции:

componentDidMount() {
    window.addEventListener("beforeunload", this.keepOnPage);
  }

  componentWillUnmount() {
    window.removeEventListener("beforeunload", this.keepOnPage);
  }

  keepOnPage = (event) => {
    const localStorageCard = JSON.parse(localStorage.getItem("card"));
    if (this.props.card === localStorageCard) {
      return;
    } else {
      let message;
      event.returnValue = message;
      return message;
    }
  };

{ ... }

const mapStateToProps = (state) => {
  return {
    card: state.card,
  };
};

export default connect(mapStateToProps)(App);

Моя единственная проблема в том, что когда я перехожу к другому маршруту, я обновляю / перезагружаю / закрываю окно , он показывает "Обновить сайт?" запросить, не меняя состояние редукции.

Есть ли лучший способ сделать это?

...