预期的行为-我加载照片对象并将其渲染到组件中。 使用下面的代码,我确实可以达到预期的效果,但是却产生了一些意想不到的效果,这些效果最终使该组件不再有用-参见两部分的进一步说明。 我真的很想深入探讨所有原因,并了解如何防止我的应用中出现此类行为。 我确实尝试了其他人类似问题的一些建议,但没有任何帮助。我不会在这里列出我尝试过的事情,因为,显然,每次尝试时-我做错了什么,因为它没有帮助。 对于任何想法和建议,我将不胜感激-我错过了一些东西,无法理解它是什么。
第1部分。 首次加载和/或刷新该组件时-我得到了多个渲染器。从Redux DevTools中,我可以观察到动作触发了两次,控制台记录了从photo值收到的任何值,显示该值在控制台中出现了6次(前3次-处于redux-store的初始状态,然后-并从照片对象的值中提取了预期值。
第2部分。 当我打开下一张照片(相同的组件,只是传递不同的match.params.id)时,该组件显然开始随机渲染。完成此重新渲染循环可能需要几秒钟,因此它有时会重新渲染数十次,有时会重新渲染100次以上,但最终总是渲染所需的信息。 分析日志后,我发现现在获取的照片的值正与之前获取的照片的值在循环中切换。循环以正确的值停止。而且previos值从何而来-我无法弄清楚,因为在获取新的照片对象之前,我先清除了redux状态下的所有数据。
组件:
//IMPORTS
const Photo = ({ getPhotoById, photo, loading, match }) => {
const [photoData, setPhotoData] = useState({
photoID: match.params.id,
imgUrl: '',
photoFileName: '',
title: '',
description: '',
albumID: '',
albumName: '',
categoryID: '',
categoryName: '',
categoryID2: '',
categoryName2: '',
categoryID3: '',
categoryName3: '',
locationID: '',
locationName: '',
contributorID: '',
contributorName: '',
contributorWeb: '',
source: '',
sourceWeb: '',
author: '',
periodID: '',
periodName: '',
license: ''
});
const {
photoID,
imgUrl,
photoFileName,
title,
description,
albumID,
albumName,
categoryID,
categoryName,
categoryID2,
categoryName2,
categoryID3,
categoryName3,
locationID,
locationName,
contributorID,
contributorName,
source,
sourceWeb,
author,
periodID,
periodName,
license
} = photoData;
useEffect(() => {
getPhotoById(photoID);
}, [getPhotoById, photoID]);
useEffect(() => {
if (loading === false) {
const {
photoID,
imgUrl,
photoFileName,
title,
description,
albumID,
albumName,
categoryID,
categoryName,
categoryID2,
categoryName2,
categoryID3,
categoryName3,
locationID,
locationName,
contributorID,
contributorName,
source,
sourceWeb,
author,
periodID,
periodName,
license
} = photo;
setPhotoData({
photoID,
imgUrl,
photoFileName,
title,
description,
albumID,
albumName,
categoryID,
categoryName,
categoryID2,
categoryName2,
categoryID3,
categoryName3,
locationID,
locationName,
contributorID,
contributorName,
source,
sourceWeb,
author,
periodID,
periodName,
license
});
}
}, [loading]);
useEffect(() => {
if (!loading) {
initOpenseadragon();
}
}, [loading]);
console.log(photoFileName, 'photoFileName');
const initOpenseadragon = () => {
OpenSeadragon({
id: 'viewer',
tileSources: `/uploads/tiles/${photoFileName}.dzi`,
prefixUrl: '/images/osd/',
showZoomControl: true,
showHomeControl: true,
showFullPageControl: true,
showRotationControl: true
});
};
return !photo && !loading ? (
<NotFound />
) : (
<Fragment>
SOME JSX
</Fragment>
);
};
Photo.propTypes = {
getPhotoById: PropTypes.func.isRequired,
// photo: PropTypes.object.isRequired,
loading: PropTypes.bool.isRequired
};
const mapStateToProps = state => {
return {
photo: state.photo.photo,
loading: state.photo.loading
};
};
export default connect(
mapStateToProps,
{ getPhotoById }
)(Photo);
动作:
export const getPhotoById = photo_id => async dispatch => {
try {
dispatch({ type: CLEAR_PHOTO });
dispatch({ type: LOAD_PHOTO });
const res = await axios.get(`/api/photo/${photo_id}`);
dispatch({
type: GET_PHOTO,
payload: res.data
});
} catch (err) {
dispatch({
type: PHOTOS_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
减速机
const initialState = {
photo: null,
photos: [],
loading: true,
error: {}
};
const photo = (state = initialState, action) => {
const { type, payload } = action;
switch (type) {
case GET_PHOTO:
return {
...state,
photo: payload,
loading: false
};
case LOAD_PHOTO:
return {
...state,
loading: true
};
case CLEAR_PHOTO:
return {
...state,
photo: null,
loading: false
};
case PHOTOS_ERROR:
return {
...state,
error: payload,
loading: false
};
default:
return state;
}
};
export default photo;
答案 0 :(得分:0)
您的问题是您要添加getPhotoById
作为挂钩的依赖项,请参见this article有关依赖项数组。
如果要防止重新渲染,可以执行以下操作:
const ref = useRef();
getPhotoByIdRef.current = getPhotoById
useEffect(() => {
getPhotoByIdRef(match.params.id)
}, [getPhotoByIdRef, match.params.id]);