首页 > 解决方案 > 卸载子组件抛出无法在 reactjs 中的卸载组件上调用 setstate

问题描述

当我卸载子组件时,我得到无法设置未安装组件警告的状态。

我想做什么?我有一个父组件 ViewItems 和子组件 ItemsList。在 ViewItems 组件中,我使用 load_items 方法从服务器检索项目列表,该方法又使用 client.get_file 方法。并将这些项目列表存储在名为“项目”的状态中。我在 componenDidMount 方法中调用了这个 load_items 方法。但是,这不会显示另一个项目的新详细信息。

给问题一个清晰的画面。考虑我在一页中呈现项目。当我单击一个项目时,它会将我带到另一个页面(在本例中为已安装的项目组件),当我单击按钮单击以查看项目详细信息时,它会列出与该项目相关的详细信息。当我单击按钮返回项目列表(我们之前所在的页面)并单击另一个项目时。它应该显示与单击的新项目相关的详细信息。

但是,在这种情况下,当我单击新项目时,它会显示以前的项目详细信息,除非页面刷新。

为了克服这个问题,在 componentDidUpdate 上我调用了这个 load_items 方法。这行得通。但是,当我不关闭子组件时,这意味着显示项目详细信息的布局......我收到无法调用 setstate on unmounted component 警告。卸载子组件后会显示此错误。

下面是代码,

class ViewItems extends React.PureComponent {
    constructor(props) {
        super(props);
        this.default_root_item = {
            name: 'Items',
            index: 0,
            children: [],
        };
        this.state = {
            root_items: this.default_root_item,
            items: [],
        };
     }

    componentDidMount() {
        this.load_items();
    }

    componentDidUpdate() {
        this.load_items();
    }

    componentWillUnmount() {
        this.unlisten_path_change();
    }

    load_items = () => {
        const file_name = 'file_name.json';
        client.get_file(this.props.item_id, file_name, 'json')
            .then((request) => {
                const items = request.response;
                this.setState({items: [this.default_root_item]});}
        this.handle_path_change(this.props.location.pathname);})};

        return (
            <ChildComponent            
                 on_close={this.handle_item_close}
                 root_item={this.state.root_item}/>)}
export default class ChildComponent extends React.PureComponent {
    <Items
        items={root_item}/>

function Items(props) {
    return (
        <ul className="Items_list">
            <div className="items">
            {props.items.map((item, index) => {
                return (
                    <Item
                        key={index}
                        item={item}
                     />
                );
            })}
            </div>
       </ul>
    );}
}

标签: reactjs

解决方案


首先,不要在没有检查 props 是否更改的情况下在 componentDidUpdate 中进行 API 调用。

第二:从 API 请求响应设置状态时,检查组件是否仍然挂载

class ViewItems extends React.PureComponent {
    constructor(props) {
        super(props);
        this.default_root_item = {
            name: 'Items',
            index: 0,
            children: [],
        };
        this.state = {
            root_items: this.default_root_item,
            items: [],
        };
        this._isMounted = true;
     }

    componentDidMount() {
        this.load_items();
    }

    componentDidUpdate(prevProps) {
        if (prevProps.item_id !== this.props.item_id) {
          this.load_items();
        }
    }

    componentWillUnmount() {
        this._isMounted = false;
        this.unlisten_path_change();
    }

    load_items = () => {
        const file_name = 'file_name.json';
        client.get_file(this.props.item_id, file_name, 'json')
            .then((request) => {
                const items = request.response;
                if (this._isMounted) {
                  this.setState({items: [this.default_root_item]});
                  this.handle_path_change(this.props.location.pathname);
                }
            })
    };

推荐阅读