Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RequestScreen.tsx 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import React, { useEffect, useRef } from 'react';
  2. import ErrorView from './ErrorView';
  3. import { useRequestLogic } from '../../utils/customHooks';
  4. import { useFocusEffect } from '@react-navigation/native';
  5. import BasicLoadingScreen from './BasicLoadingScreen';
  6. import i18n from 'i18n-js';
  7. import { API_REQUEST_CODES, REQUEST_STATUS } from '../../utils/Requests';
  8. export type RequestScreenProps<T> = {
  9. request: () => Promise<T>;
  10. render: (
  11. data: T | undefined,
  12. loading: boolean,
  13. lastRefreshDate: Date | undefined,
  14. refreshData: (newRequest?: () => Promise<T>) => void,
  15. status: REQUEST_STATUS,
  16. code?: API_REQUEST_CODES
  17. ) => React.ReactElement;
  18. cache?: T;
  19. onCacheUpdate?: (newCache: T) => void;
  20. onMajorError?: (status: number, code?: number) => void;
  21. showLoading?: boolean;
  22. showError?: boolean;
  23. refreshOnFocus?: boolean;
  24. autoRefreshTime?: number;
  25. refresh?: boolean;
  26. onFinish?: () => void;
  27. };
  28. export type RequestProps = {
  29. refreshData: () => void;
  30. loading: boolean;
  31. };
  32. type Props<T> = RequestScreenProps<T>;
  33. const MIN_REFRESH_TIME = 5 * 1000;
  34. export default function RequestScreen<T>(props: Props<T>) {
  35. const refreshInterval = useRef<number>();
  36. const [
  37. loading,
  38. lastRefreshDate,
  39. status,
  40. code,
  41. data,
  42. refreshData,
  43. ] = useRequestLogic<T>(
  44. props.request,
  45. props.cache,
  46. props.onCacheUpdate,
  47. props.refreshOnFocus,
  48. MIN_REFRESH_TIME
  49. );
  50. // Store last refresh prop value
  51. const lastRefresh = useRef<boolean>(false);
  52. useEffect(() => {
  53. // Refresh data if refresh prop changed and we are not loading
  54. if (props.refresh && !lastRefresh.current && !loading) {
  55. refreshData();
  56. // Call finish callback if refresh prop was set and we finished loading
  57. } else if (lastRefresh.current && !loading && props.onFinish) {
  58. props.onFinish();
  59. }
  60. // Update stored refresh prop value
  61. if (props.refresh !== lastRefresh.current) {
  62. lastRefresh.current = props.refresh === true;
  63. }
  64. }, [props, loading, refreshData]);
  65. useFocusEffect(
  66. React.useCallback(() => {
  67. if (!props.cache && props.refreshOnFocus !== false) {
  68. refreshData();
  69. }
  70. if (props.autoRefreshTime && props.autoRefreshTime > 0) {
  71. refreshInterval.current = setInterval(
  72. refreshData,
  73. props.autoRefreshTime
  74. );
  75. }
  76. return () => {
  77. if (refreshInterval.current) {
  78. clearInterval(refreshInterval.current);
  79. }
  80. };
  81. // eslint-disable-next-line react-hooks/exhaustive-deps
  82. }, [props.cache, props.refreshOnFocus])
  83. );
  84. if (data === undefined && loading && props.showLoading !== false) {
  85. return <BasicLoadingScreen />;
  86. } else if (
  87. data === undefined &&
  88. status !== REQUEST_STATUS.SUCCESS &&
  89. props.showError !== false
  90. ) {
  91. return (
  92. <ErrorView
  93. status={status}
  94. loading={loading}
  95. button={{
  96. icon: 'refresh',
  97. text: i18n.t('general.retry'),
  98. onPress: () => refreshData(),
  99. }}
  100. />
  101. );
  102. } else {
  103. return props.render(
  104. data,
  105. loading,
  106. lastRefreshDate,
  107. refreshData,
  108. status,
  109. code
  110. );
  111. }
  112. }