开玩笑警告:无法在已卸载的组件上执行React状态更新。在componentDidMount上

时间:2019-08-18 09:52:41

标签: jestjs fetch enzyme

我正在尝试测试componentDidMount中的提取调用。尝试不同的解决方案,但总是死胡同。目前我有

组件

    import React, { Component } from 'react';
import Seatmap from 'react-seatmap';
import '../../style/main.scss';
import seats from '../../seatData';
import Ticket from '../Ticket';

class Booking extends Component {

  constructor(props){
    super(props);

    this.state = {
      row: null,
      number: null,
      data: [],
      selected: null,
      isLoaded: false
    }

    this.addSeatCallback = this.addSeatCallback.bind(this);
    this.removeSeatCallback = this.removeSeatCallback.bind(this);
  }

  controller = new AbortController();

  async fetchData() {
    await fetch(window.location.protocol + window.location.hostname,{
      signal: this.controller.signal
    })
      .then(res => seats)
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            data: this.formatSeatData(result)
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      );
  }

  async componentDidMount(){
    await this.fetchData();
  }

  componentWillUnmount() {
    this.controller.abort();
  }

  getIndexFromLetter(letter) {
    return letter.charCodeAt(0) - 65;
  }

  formatSeatData(seats){
    const rows = [];
    seats.seats.map( (seat,i) => {
      const arr = seat.seatNumber.split(/([0-9]+)/).filter(Boolean);
      seat.number = arr[0];
      seat.isReserved = !seat.available;
      const index = this.getIndexFromLetter(arr[1]);
      if(typeof rows[index] === 'undefined') {
        rows[index] = [];
      }
      rows[index].push(seat);
      return true;
    });

    return rows;
  }

  addSeatCallback(row, number) {
    const { data } = this.state;
    const index = this.getIndexFromLetter(row);
    this.setState({ row, number, selected: data[index][number-1] });
  }

  removeSeatCallback(row, number) {
    this.setState({row: null, number: null, selected: null});
  }

  render() {
    const { data, selected } = this.state;
    if(Object.keys(data).length>0){
      return (
        <div className="container-fluid text-center">
          <div className="" style={{float:'left', padding: '10px', marginTop:'10px'}}>
            <Seatmap rows={data} maxReservableSeats={1} alpha addSeatCallback={this.addSeatCallback} removeSeatCallback={this.removeSeatCallback} />
          </div>
          <div className="" style={{float:'left', padding: '10px'}}>
            <Ticket selected={selected} />
          </div>
        </div>
      );
    }
    return null;
  }
}

export default Booking;

测试

import React from 'react';
import ReactDOM from 'react-dom';
import Booking from '../../src/components/Booking';
import seats from '../../src/seatData';
import { shallow } from 'enzyme';


describe('Booking', () => {

  it('renders without crashing', () => {
    const div = document.createElement('div');
    ReactDOM.render(<Booking />, div);
    ReactDOM.unmountComponentAtNode(div);
  });

  let wrapper;
  beforeEach(() => {
    wrapper = shallow(<Booking />, { disableLifecycleMethods: true });
  });

  afterEach(() => {
    wrapper.unmount();
  });

  it("must render a loading span before api call success", () => {
    // expect(wrapper.find("span.loading").length).toBe(1);
  });

  it("componentDidMount", (done) => {

    const spyDidMount = jest.spyOn(Booking.prototype,"componentDidMount");
    fetch.mockImplementation(() => {
      return Promise.resolve({
        status: 200,
        json: () => {
          return Promise.resolve({
            seats:{}
          });
        }
      });
    });

    const didMount = wrapper.instance().componentDidMount();

    expect(spyDidMount).toHaveBeenCalled();
    didMount.then(() => {
      wrapper.update();
      expect(wrapper.find("div.seatmap_container"));
      expect(wrapper.find("spans.loading").length).toBe(0);
      spyDidMount.mockRestore();
      fetch.mockClear();
      done();
    });
  });
});

这是我的仓库https://github.com/shorif2000/elucidat-javascript-test

错误

 PASS  test/components/Booking.test.js
  Booking
    ✓ renders without crashing (29ms)
    ✓ must render a loading span before api call success (1ms)
    ✓ componentDidMount (14ms)

  console.error node_modules/react-dom/cjs/react-dom.development.js:545
    Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
        in Booking

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        2.145s
Ran all test suites matching /test\/components\/Booking.test.js/i.

0 个答案:

没有答案