警告:无法在没有 useEffect 的情况下对卸载的组件执行 React 状态更新

时间:2021-03-23 19:10:51

标签: javascript reactjs redux

大家好,我有一个获取产品信息并呈现它的基本组件。它有一个名为 onAaddToWishList 的方法,它获取产品 ID,从 API 获取数据并将其添加到我的愿望清单中。

const Product = (props) => {
    const [loading, setLoading] = useState(false);

    const onAddToWishlist = (e, id) => {
        e.preventDefault();

        if (!loading) {
            setLoading(true)

            instance.get(`/products/product/${id}`, {
                headers: {
                    'X-Auth-Token': findToken()
                }
            })
                .then(response => {
                    if (response.data.food) {
                        alert('Product added')

                        props.addToWishlist(response.data.food);

                        console.log(response.data.food)
                    }
                    else {
                        alert('Product not found')
                    }

                    setLoading(false);
                })
                .catch(err => {
                    console.log(err)

                    setLoading(false);

                    alert('Error occured.try again')
                })
        }
    }

    return (
        <div className="ProductCard">
            <div className="ProductCard--Image">
                <img src={props.image} alt="iclereu" />
            </div>
            <div className="ProductCard--Container">
                <h1>{props.title}</h1>
                <p>{props.description}</p>
                <span>&#8380; {props.price}</span>
                <div className="ProductCard--Nav">
                    <div className="ProductCard--Link">
                        <Link to="/">View more</Link>
                    </div>
                    <div className="ProductCard--Link">
                        <a
                            onClick={(e) => onAddToWishlist(e, props.id)}
                            href="#"
                        >
                            {!loading ? "+Wishlist" : "Loading..."}
                        </a>
                    </div>
                </div>
            </div>
        </div>
    )
}

const mapStateToProps = (state) => {
    return {
        wishlist: state.wishlist
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        addToWishlist: (product) => dispatch(wishlistActions.addToWishList(product))
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Product)

这是我的 addToWishList 操作:

const addToWishList = (product) => {
    return dispatch => {
        let wishlist = [...store.getState().wishlist];
        let exists = wishlist.find(prod => prod.product._id === product._id);

        if (!exists) {
            wishlist = [...wishlist, {
                product: product,
                count: 1
            }]
        }
        else {
            let index = wishlist.findIndex(prod => prod.product._id === product._id);
            wishlist[index].count++;
        }

        dispatch({ type: "ADD_TO_WISHLIST", wishlist: wishlist })
    }
}

props.addToWishlist 是用于 redux 操作的函数(它将数据保存到 redux 存储(wishlist))。问题是无论我在此操作中做什么,我都会收到以下警告:

<块引用>

警告:无法对已卸载的组件执行 React 状态更新。 这是一个空操作,但它表明您的应用程序中存在内存泄漏。 修复,取消 useEffect 中的所有订阅和异步任务 清理功能。

但我不使用 useEffect 钩子。它实际上有效(它向 wishlist 添加了一个产品)但是警告很烦人,就像我做错了什么一样。即使我安慰了 redux 操作的参数,它也会给出相同的错误。如果有人帮助我,我将不胜感激

1 个答案:

答案 0 :(得分:1)

原因是你的组件的 props 正在改变(wishlist)组件正在重新渲染,此时 setLoading 正在尝试更新已卸载组件的状态。对于这个例子, useEffect 并不是很有用。 最快的解决方案是将加载状态也保留在 redux 存储中,并从此组件中删除 const [loading, setLoading] = useState(false);。 此外,值得一提的是,最好将表示和 API 交互分解。我可以为您推荐两种简单的 redux 方法:https://www.npmjs.com/package/redux-api-middlewarehttps://www.npmjs.com/package/redux-thunk