【问题标题】:ComponentwillMount is called twiceComponentwillMount 被调用两次
【发布时间】:2016-12-13 09:01:44
【问题描述】:

I'm my componentWillMount() 每次切换路线时都会被调用。

还有其他方法可以处理商店状态的变化吗?

当我第一次使用这两个功能时没问题,但是当我切换路线并返回并尝试再次使用它们时,我收到此消息

warning.js:45 Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.

InventoryList.js

import React from "react";
import InventoryItem from "../components/InventoryItem";
import InventoryItemStore from "../stores/InventoryItemStore";
import { Link } from "react-router";

export default class InventoryList extends React.Component {
    constructor() {
        super();
        this.state = {
            items: InventoryItemStore.getAll(),
        }
    }

    componentWillMount() {
        InventoryItemStore.on("change", () => {
            this.setState({
                items: InventoryItemStore.getAll()
            });
        });
    }

    render(...);
}

InventoryStore.js

import { EventEmitter } from "events";

import dispatcher from "../dispatcher";

class InventoryItemStore extends EventEmitter {

    constructor() {
        super()
        this.items = [
            {
                id: 1,
                title: "first item",
                stockQuantity: 10
            },
            {
                id: 2,
                title: "second item",
                stockQuantity: 5
            }
        ];
    }

    getAll() {
        return this.items;
    }

    // Adds new item to the inventory store
    addItem( title, stockQuantity ) {
        const id = Date.now();
        this.items.push({
            id,
            title, // We don't have to do title: title because of ES6... Thx ES6
            stockQuantity
        });

        this.emit("change");
    }


    /**
     * Lower the stock quantity of certain item
     * @param  {integer} id
     * @param  {integer} stockQuantity
     */
    lowerQuantity( id, orderQuantity ) {

        this.items.map((item) => {

            if ( item.id == id ) {
                item.stockQuantity = item.stockQuantity - orderQuantity;
            }

        });

        this.emit("change");

    }


    handleActions( action ) {

        switch( action.type ) {
            case "ADD_ITEM": {
                const { title, stockQuantity } = action;
                this.addItem( title, stockQuantity );
            }
            case "LOWER_QUANTITY": {
                const { id, orderQuantity } = action;
                this.lowerQuantity( id, orderQuantity );
            }
        }

    }

}

const inventoryItemStore = new InventoryItemStore;

dispatcher.register(inventoryItemStore.handleActions.bind(inventoryItemStore));

export default inventoryItemStore;

【问题讨论】:

  • 您是否会尝试编写一些代码来从 componentWillUnmount 的 InventoryItemStore 中解除“更改”事件的绑定?更改 react-router 时,您的组件将卸载然后重新安装。如果您不从存储中取消绑定“更改”事件,最后会保留两个事件。它会导致事件监听器被调用两次。
  • 感谢您的评论,您是对的,但我不知道要在componentWillUnmount 中添加什么代码才能真正删除更改事件侦听器

标签: javascript reactjs flux


【解决方案1】:

您的组件会在您每次更改路由时卸载,并且在您更改回路由时会安装一个新组件。

由于您使用 InventoryItemStore.on 注册了一个事件处理程序,但从未取消注册它,因此您会留下两个正在监听 change 的组件,而一个未安装的组件会引发错误。

使用componentWillUnmount 取消注册您的组件,这样它就不会像幽灵一样徘徊并在您导航返回时困扰您。

有关更多生命周期挂钩,请参阅 React lifecycle

【讨论】:

  • 哦,非常感谢,我不知道componentWillUnmount 的确切用途是什么,但现在我明白了:)
  • 但是你认为你可以指出,我应该把componentWillUnmount放在哪里?
  • 在 InventoryList.js
  • 对不起,我问错了。如何实际卸载事件。我放置了componentWillUnmount,但我不知道如何取消绑定“更改”事件监听器
  • @JakubKohout 你使用removeListener,它在this答案中得到了展示。
猜你喜欢
  • 1970-01-01
  • 2017-04-27
  • 1970-01-01
  • 2016-04-01
  • 2012-05-05
  • 2017-01-19
  • 2014-02-04
  • 2016-01-30
  • 2015-12-20
相关资源
最近更新 更多