简体   繁体   中英

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

I have form with a drag and drop component where I can upload images, after this I send these pictures with axios to my backend and save it on server side and then re-render it on my client side in a preview mode. My problem is, that if a user uploads some pictures and after that he switches to another page without submitting the form the added pictures are staying on my server side for no reason. To solve this problem I tried to detect at cleanup function if the user leaves the page and this part is working fine.

And the problem:Inside the useEffect clear function I tried to access the state where I stored the image's path, but it always gave me the initial state. If I added the state as an input to useEffect then in every image adding/state modifying the clear function was fired and caused me error/unwanted behaviour. So I decided to move my image links to a global redux store but when I try to acess this store I got the store's inital state too (which is an empty array) however there were elements in it. So my question is how to access the state/global state and clean my backend images in the clear function?

My code

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

This is a classic closure issue, you cannot add dependencies to useEffect because you want the function to only run on component unmount but due to the fact that your useEffect only runs on initial render, the variables it used from closure are all stale when the component unmounts.

To solve such scenarios, you will have to store state in ref like

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
    }

NOTE: If you do not like this approach, you can fallback to class components where you will not face this issues implementing componentWillUnmount.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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