React Hooks和redux会导致不必要的渲染和一些意外效果

预期的行为-我加载照片对象并将其渲染到组件中。 使用下面的代码,我确实可以达到预期的效果,但是却产生了一些意想不到的效果,这些效果最终使该组件不再有用-参见两部分的进一步说明。 我真的很想深入探讨所有原因,并了解如何防止我的应用中出现此类行为。 我确实尝试了其他人类似问题的一些建议,但没有任何帮助。我不会在这里列出我尝试过的事情,因为,显然,每次尝试时-我做错了什么,因为它没有帮助。 对于任何想法和建议,我将不胜感激-我错过了一些东西,无法理解它是什么。

第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,license
      } = photo;

      setPhotoData({
        photoID,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;
vorlor 回答:React Hooks和redux会导致不必要的渲染和一些意外效果

您的问题是您要添加getPhotoById作为挂钩的依赖项,请参见this article有关依赖项数组。

如果要防止重新渲染,可以执行以下操作:

const ref = useRef();




getPhotoByIdRef.current = getPhotoById

useEffect(() => {
  getPhotoByIdRef(match.params.id)
},[getPhotoByIdRef,match.params.id]);
本文链接:https://www.f2er.com/3136920.html

大家都在问