【问题标题】:How to access state/redux store in the useEffect's cleanup function?如何在 useEffect 的清理功能中访问 state/redux 存储?
【发布时间】:2021-04-08 15:43:41
【问题描述】:

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

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

我的代码

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

【问题讨论】:

  • 将它们添加到依赖数组以观察更新。
  • 如果我按照我所说的那样添加它们,这会导致我不想要的行为,因为在每个图像添加/删除等时都会调用清理功能。

标签: javascript reactjs redux


【解决方案1】:

这是一个典型的闭包问题,你不能向 useEffect 添加依赖,因为你希望函数只在组件卸载时运行,但由于你的 useEffect 只在初始渲染时运行,它从闭包中使用的变量都是陈旧的当组件卸载时。

要解决这种情况,您必须将状态存储在 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
    }

注意:如果您不喜欢这种方法,可以回退到课堂 实现 componentWillUnmount 时不会遇到此问题的组件。

【讨论】:

  • 谢谢你终于成功了 :) Huuge 谢谢。
  • 另外,请确保使用“useRef()”而不是“createRef()”。在这种情况下,后一个选项将不起作用。
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 2021-01-04
  • 2020-02-16
  • 2021-02-07
  • 1970-01-01
  • 2020-03-05
  • 2021-03-24
  • 2021-10-31
相关资源
最近更新 更多