![](/img/trans.png)
[英]Return undefined Redux store state in useEffect() function
[英]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.