繁体   English   中英

如何在 useEffect 的清理 function 中访问 state/redux 存储?

[英]How to access state/redux store in the useEffect's cleanup function?

我有一个带有拖放组件的表单,我可以在其中上传图像,之后我将这些带有 axios 的图片发送到我的后端并将其保存在服务器端,然后在我的客户端以预览模式重新渲染它。 我的问题是,如果用户上传了一些图片,然后他在没有提交表单的情况下切换到另一个页面,那么添加的图片会无缘无故地留在我的服务器端。 为了解决这个问题,我尝试在清理 function 时检测用户是否离开页面并且这部分工作正常。

问题是:在 useEffect clear function 内部,我尝试访问存储图像路径的 state,但它总是给我初始的 Z9ED39E2EA931586B6A985A6942EF573E。 如果我添加了 state 作为 useEffect 的输入,那么在每个图像添加/状态中修改清除 function 被触发并导致我错误/不需要的行为。 因此,我决定将我的图像链接移动到全局 redux 商店,但是当我尝试访问这家商店时,我也得到了商店的初始 state (这是一个空数组)但是里面有元素。 所以我的问题是如何访问状态/全局 state 并在清晰的 function 中清理我的后端图像?

我的代码

function Product(props) {
 const globalStoreImgaes = useSelector(state => state.product.addedImages)
 const [Images,setImages] = useState([])
 
useEffect(() => {
        const initialObj = {
         ...key:values
        }
        dispatch(setProduct(initialObj)); // here I initialize my global state of my product when the page loads (the setProduct function transforms the initial object to another structure)
    }, []) // eslint-disable-line react-hooks/exhaustive-deps
    
    useEffect(() => {
            return function cleanup() {
                console.log('Leaving',globalStoreImgaes)
                console.log('Leaving',Images) // both of them are [] arrays however I have items in it

                ...axios call to delete from global store

             };
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

const updateImages = (newImages) => {
        dispatch(refreshImage(newImages)) // this is where i update the global store
        setImages(newImages) // and my state too
    }
return (
 <Prompt when={isBlocking} message="There are unsaved datas. Are you sure you want to leave?"/> // if the user clicks yes the clear function activates 

 ...somecode)
}
export default Product

这是一个经典的闭包问题,您不能将依赖项添加到 useEffect 因为您希望 function 仅在组件卸载时运行,但由于您的 useEffect 仅在初始渲染时运行,它从闭包中使用的变量在组件时都是陈旧的卸载。

要解决这种情况,您必须将 state 存储在 ref 中,例如

function Product(props) {
 const globalStoreImgaes = useSelector(state => state.product.addedImages)
 const [Images,setImages] = useState([])
 const ImageRef = useRef({globalStoreImages, Images})
 useEffect(() => {
    ImageRef.current = {globalStoreImages, Images};
 }, [globalStoreImages, Images])
 
useEffect(() => {
        const initialObj = {
         ...key:values
        }
        dispatch(setProduct(initialObj)); // here I initialize my global state of my product when the page loads (the setProduct function transforms the initial object to another structure)
    }, []) // eslint-disable-line react-hooks/exhaustive-deps
    
    useEffect(() => {
            return function cleanup() {
                console.log('Leaving',ImagesRef.current.globalStoreImgaes)
                console.log('Leaving',ImagesRef.current.Images) 

                ...axios call to delete from global store

             };
    }, []); // eslint-disable-line react-hooks/exhaustive-deps

    const updateImages = (newImages) => {
        dispatch(refreshImage(newImages)) // this is where i update the global store
        setImages(newImages) // and my state too
    }

注意:如果您不喜欢这种方法,您可以回退到 class 组件,在这些组件中您不会遇到实施 componentWillUnmount 的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM