簡體   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