ListComponent.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* eslint-disable no-console */
  2. /* eslint-disable react/jsx-props-no-spreading */
  3. /* eslint-disable no-underscore-dangle */
  4. import React from "react";
  5. import { Divider, List, Layout } from "@ui-kitten/components";
  6. import { useFocusEffect } from "@react-navigation/native";
  7. import { useModel } from "flooks";
  8. import { initDataState, DataListReducer } from "../Redux/DataListRedux";
  9. import EmptyComponent from "./EmptyComponent";
  10. export default function ListComponent(props) {
  11. const { clearLoading } = useModel("loadingModel");
  12. const [state, dispatch] = React.useReducer(DataListReducer, initDataState);
  13. const { page, size, loading, refreshing, dataList } = state;
  14. const {
  15. getInfo,
  16. renderItem,
  17. ListHeaderComponent,
  18. style,
  19. separatorStyle,
  20. ListFooterComponent,
  21. showEmpty,
  22. emptyEvent,
  23. showList,
  24. extraData,
  25. delId,
  26. startState, // 父级调刷新
  27. initialNumToRender,
  28. saveList, // 保持状态
  29. list$,
  30. } = props;
  31. function setList(newList) {
  32. dispatch({
  33. type: "setInfo",
  34. payload: { list: newList, finish: true },
  35. });
  36. }
  37. if (list$) {
  38. list$.useSubscription(info => {
  39. const list = [...dataList];
  40. let newList = [];
  41. newList = info.changeEvent(list, info.list, info.type, info.extra);
  42. setList(newList);
  43. });
  44. }
  45. function getList() {
  46. if (getInfo != null) {
  47. return getInfo(page, size).then(res => {
  48. if (emptyEvent) {
  49. if (res.numberOfElements === 0) {
  50. emptyEvent(true);
  51. } else {
  52. emptyEvent(false);
  53. }
  54. }
  55. dispatch({
  56. type: "setInfo",
  57. payload: { list: res.content, finish: res.last },
  58. });
  59. });
  60. }
  61. return Promise.reject();
  62. }
  63. React.useEffect(() => {
  64. if (delId) {
  65. const list = [...dataList];
  66. const Index = list.findIndex(item => {
  67. return item.id === delId;
  68. });
  69. if (Index !== -1) {
  70. dispatch({
  71. type: "remove",
  72. payload: { index: Index },
  73. });
  74. }
  75. }
  76. }, [delId]);
  77. // 刷新接口
  78. function onRefresh() {
  79. dispatch({ type: "startRefresh" });
  80. getList()
  81. .then(() => {
  82. dispatch({ type: "refreshSuccess" });
  83. })
  84. .catch(e => {
  85. dispatch({
  86. type: "refreshError",
  87. payload: { error: e.message },
  88. });
  89. })
  90. .finally(() => {
  91. clearLoading();
  92. });
  93. }
  94. // 到页面底部加载更多
  95. function gotEnd() {
  96. dispatch({ type: "startPageMore" });
  97. getList()
  98. .then(() => {
  99. dispatch({ type: "pageMoreSuccess" });
  100. })
  101. .catch(e => {
  102. dispatch({
  103. type: "pageMoreError",
  104. payload: { error: e.message },
  105. });
  106. })
  107. .finally(() => {
  108. clearLoading();
  109. });
  110. }
  111. useFocusEffect(
  112. React.useCallback(() => {
  113. if (saveList !== true) {
  114. dispatch({
  115. type: "clear",
  116. });
  117. }
  118. if (startState !== false) {
  119. onRefresh();
  120. }
  121. }, [])
  122. );
  123. React.useEffect(() => {
  124. if (startState) {
  125. onRefresh();
  126. }
  127. }, [startState]);
  128. const changePorps = React.useMemo(() => {
  129. let _props = { renderItem: () => <Layout /> };
  130. if (showList !== false) {
  131. _props = { renderItem };
  132. if (extraData) {
  133. _props = {
  134. ..._props,
  135. extraData,
  136. };
  137. }
  138. }
  139. return _props;
  140. }, [showList, extraData]);
  141. const ListEmptyComponent = React.useMemo(() => {
  142. if (showEmpty && !refreshing && !loading) {
  143. return EmptyComponent;
  144. }
  145. return <></>;
  146. }, [showEmpty, refreshing, loading]);
  147. return (
  148. <List
  149. refreshing={refreshing}
  150. style={[style]}
  151. data={dataList}
  152. removeClippedSubviews
  153. initialNumToRender={initialNumToRender || 10}
  154. ListHeaderComponent={ListHeaderComponent}
  155. ListEmptyComponent={ListEmptyComponent}
  156. onRefresh={onRefresh}
  157. onEndReached={0.2}
  158. ItemSeparatorComponent={() => <Divider style={[separatorStyle]} />}
  159. onEndReachedThreshold={gotEnd}
  160. ListFooterComponent={ListFooterComponent}
  161. {...changePorps}
  162. />
  163. );
  164. }