Skip to content

Commit 61e8f88

Browse files
authored
Merge pull request #30 from itenl/dev-1.1.7
Dev 1.1.7
2 parents 11196b7 + e8e2395 commit 61e8f88

File tree

5 files changed

+191
-30
lines changed

5 files changed

+191
-30
lines changed

README-zh_CN.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* [Snapshot](#Snapshot)
2424

2525
## <a name="features"/>Features
26-
* 支持为每个 `Screen` 设置下拉刷新与上滑加载更多(生命周期注入形式)
26+
* 支持为每个 `Screen` 设置下拉刷新与上滑加载更多(生命周期注入或属性注入)
2727
* Tabs 支持固定自适应与水平滚动两种配置方式
2828
* 允许为每个 `Screen` 独立配置 `Sticky` 组件
2929
* 允许为每个 `Tab` 独立配置自定义的徽章
@@ -96,7 +96,52 @@ function App() {
9696
toProps: {
9797
xx: 123,
9898
},
99-
},
99+
}, {
100+
screen: ({
101+
layoutHeight,
102+
refresh,
103+
scrollTo,
104+
toTabView,
105+
initScreen,
106+
onRefresh,
107+
onEndReached,
108+
}) => {
109+
// The code is required
110+
initScreen();
111+
const [datetime, setDatetime] = useState(Date.now());
112+
useEffect(() => {
113+
setInterval(() => {
114+
setDatetime(Date.now());
115+
}, 1000);
116+
}, []);
117+
onRefresh((toggled) => {
118+
toggled(true);
119+
alert("onRefresh start");
120+
setTimeout(() => {
121+
toggled(false);
122+
alert("onRefresh stop");
123+
}, 3000);
124+
});
125+
onEndReached(() => {
126+
alert("onEndReached");
127+
});
128+
return (
129+
<View
130+
style={{
131+
flex: 1,
132+
backgroundColor: "#151723",
133+
justifyContent: "center",
134+
alignItems: "center",
135+
}}
136+
>
137+
<Text style={{ color: "#ffffff" }}>
138+
Test function component {datetime}
139+
</Text>
140+
</View>
141+
);
142+
},
143+
tabLabel: "TestFunctionComponent",
144+
}
100145
]}
101146
tabsStyle={{}}
102147
tabWrapStyle={{}}
@@ -116,7 +161,7 @@ function App() {
116161
onBeforeEndReached={next => {
117162
next();
118163
}}
119-
onTabviewChanged={index => {
164+
onTabviewChanged={(index, tabLabel, isFirst) => {
120165
alert(index);
121166
}}
122167
header={() => {
@@ -160,7 +205,7 @@ Prop | Type | Default | Description
160205
**`onEndReachedThreshold`** | Number | 0.2 | 触底回调阈值
161206
**`onBeforeRefresh`** | Function | null | 下拉刷新前置函数, 执行 **`next`** 将执行Screen中 **`onRefresh`** 函数,执行 **`toggled`** 将切换系统loading,可传 true / false 进行指定 (回调含有 **`next`** , **`toggled`** 两个形参)
162207
**`onBeforeEndReached`** | Function | null | 上滑加载更多前置函数, 执行next将执行Screen中 **`onEndReached`** 函数 (回调含有 **`next`** 形参)
163-
**`onTabviewChanged`** | Function | null | Tab切换完成回调 (回调含有 **`index`**, **`tabLabel`** 两个形参)
208+
**`onTabviewChanged`** | Function | null | Tab切换完成回调 (回调含有 **`index`**, **`tabLabel`**, **`isFirst`** 形参)
164209
**`screenScrollThrottle`** | Number | 60 | **`Screen`** 横向滑动时节流参数,单位 (毫秒)
165210
**`header`** | Function / JSX Element / Class Component | null | 顶部组件 (若是函数需要返回 Element)
166211
**`stickyHeader`** | Function / JSX Element / Class Component | null | 顶部带吸顶效果组件 (若是函数需要返回 Element)
@@ -224,7 +269,7 @@ Type | Description
224269
JSX Element | 基于当前Tab进行渲染的 徽章 / 悬浮 Tips 等
225270

226271

227-
## <a name="InjectionLifecycle"/>Injection lifecycle to Screen
272+
## <a name="InjectionLifecycle"/>Injection lifecycle to Screen(仅在类组件)
228273

229274
Name | Type | Description
230275
----------------- | -------- | -----------
@@ -243,6 +288,9 @@ Name | Type | Description
243288
**`layoutHeight.header`** | Number | Header 高度
244289
**`layoutHeight.tabs`** | Number | Tabs 高度
245290
**`layoutHeight.screen`** | Number | 视图 高度
291+
**`initScreen`** | Function | (仅在函数组件) 如果是函数组件则必须调用
292+
**`onRefresh`** | Function | (仅在函数组件) < [阅读 onRefresh 描述](#InjectionLifecycle) >
293+
**`onEndReached`** | Function | (仅在函数组件) < [阅读 onEndReached 描述](#InjectionLifecycle) >
246294

247295
## <a name="InjectionStickyProps"/>Injection props to Sticky
248296

README.md

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Based on pure `JS` scripts, without relying on native, no need for `react-native
2323
* [Snapshot](#Snapshot)
2424

2525
## <a name="features"/>Features
26-
* Support to individually set pull-down refresh and up-slide load for each screen (life cycle injection form)
26+
* Support to individually set pull-down refresh and up-slide load for each screen (Lifecycle injection or props injection)
2727
* Flex Tabs and multiple Tabs horizontal scrolling support configuration method
2828
* Allow to set up each Screen’s own Sticky component
2929
* Custom badges can be configured for each Tab
@@ -96,7 +96,52 @@ function App() {
9696
toProps: {
9797
xx: 123,
9898
},
99-
},
99+
}, {
100+
screen: ({
101+
layoutHeight,
102+
refresh,
103+
scrollTo,
104+
toTabView,
105+
initScreen,
106+
onRefresh,
107+
onEndReached,
108+
}) => {
109+
// The code is required
110+
initScreen();
111+
const [datetime, setDatetime] = useState(Date.now());
112+
useEffect(() => {
113+
setInterval(() => {
114+
setDatetime(Date.now());
115+
}, 1000);
116+
}, []);
117+
onRefresh((toggled) => {
118+
toggled(true);
119+
alert("onRefresh start");
120+
setTimeout(() => {
121+
toggled(false);
122+
alert("onRefresh stop");
123+
}, 3000);
124+
});
125+
onEndReached(() => {
126+
alert("onEndReached");
127+
});
128+
return (
129+
<View
130+
style={{
131+
flex: 1,
132+
backgroundColor: "#151723",
133+
justifyContent: "center",
134+
alignItems: "center",
135+
}}
136+
>
137+
<Text style={{ color: "#ffffff" }}>
138+
Test function component {datetime}
139+
</Text>
140+
</View>
141+
);
142+
},
143+
tabLabel: "TestFunctionComponent",
144+
}
100145
]}
101146
tabsStyle={{}}
102147
tabWrapStyle={{}}
@@ -116,7 +161,7 @@ function App() {
116161
onBeforeEndReached={next => {
117162
next();
118163
}}
119-
onTabviewChanged={index => {
164+
onTabviewChanged={(index, tabLabel, isFirst) => {
120165
alert(index);
121166
}}
122167
header={() => {
@@ -160,7 +205,7 @@ Prop | Type | Default | Description
160205
**`onEndReachedThreshold`** | Number | 0.2 | Bottom callback threshold
161206
**`onBeforeRefresh`** | Function | null | Pull down to refresh the pre-functions, execute **`next`** to execute **`onRefresh`** function in Screen, execute **`toggled`** to switch system loading, you can pass true / false to specify (callback contains **`next`**, **`toggled`** two formal parameters)
162207
**`onBeforeEndReached`** | Function | null | Slide up to load more pre-functions, execute next will execute the **`onEndReached`** function in the Screen (callback contains **`next`** formal parameters)
163-
**`onTabviewChanged`** | Function | null | Tab switch completion callback (callback contains **`index`**, **`tabLabel`** two formal parameters)
208+
**`onTabviewChanged`** | Function | null | Tab switch completion callback (callback contains **`index`**, **`tabLabel`**, **`isFirst`** parameters)
164209
**`screenScrollThrottle`** | Number | 60 | **`Screen`** Throttle parameters during lateral sliding, Unit (ms)
165210
**`header`** | Function / JSX Element / Class Component | null | Top component (if the function needs to return Element)
166211
**`stickyHeader`** | Function / JSX Element / Class Component | null | Top component (if the function needs to return Element) for sticky
@@ -208,7 +253,7 @@ Name | Type | Description
208253

209254
Name | Type | Description
210255
----------------- | -------- | -----------
211-
**`screen`** | Class Component | Screen class components
256+
**`screen`** | Class / Function Component | Screen components ( If the function component must call initScreen )
212257
**`sticky`** | Class Component | Sticky component, The context of this type of component will be returned in the instance
213258
**`tabLabel`** | String | Tab display name
214259
**`tabLabelRender`** | Function | Custom Tab rendering function, priority is higher than **`tabLabel`**
@@ -222,7 +267,7 @@ Type | Description
222267
JSX Element | Badges/Hovering Tips, etc. rendered based on the current Tab
223268

224269

225-
## <a name="InjectionLifecycle"/>Injection lifecycle to Screen
270+
## <a name="InjectionLifecycle"/>Injection lifecycle to Screen (On Class Component)
226271

227272
Name | Type | Description
228273
----------------- | -------- | -----------
@@ -241,6 +286,9 @@ Name | Type | Description
241286
**`layoutHeight.header`** | Number | Total height of the Header
242287
**`layoutHeight.tabs`** | Number | Total height of the Tabs
243288
**`layoutHeight.screen`** | Number | Total height of the Screen
289+
**`initScreen`** | Function | (On Function Component) If it is a function component, it must be called
290+
**`onRefresh`** | Function | (On Function Component) < [Read onRefresh description](#InjectionLifecycle) >
291+
**`onEndReached`** | Function | (On Function Component) < [Read onEndReached description](#InjectionLifecycle) >
244292

245293
## <a name="InjectionStickyProps"/>Injection props to Sticky
246294

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@itenl/react-native-scrollable-tabview",
3-
"version": "1.1.6",
3+
"version": "1.1.7",
44
"description": "react-native-scrollable-tabview",
55
"main": "index.js",
66
"scripts": {

src/index.js

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Carousel from '@itenl/react-native-snap-carousel';
55
import HocComponent from './HocComponent';
66
import _throttle from 'lodash.throttle';
77
import packagejson from '../package.json';
8+
import { initScreen, triggerOnce, refreshMap, onRefresh, triggerRefresh, onEndReached, triggerEndReached } from './useRefreshEndReached';
89
const deviceWidth = Dimensions.get('window').width;
910

1011
const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);
@@ -231,9 +232,14 @@ export default class ScrollableTabView extends React.Component {
231232
return (
232233
props.stacks &&
233234
props.stacks.map((item, index) => {
234-
if (item.screen && !item.screen.__HOCNAME__) {
235-
this._makeStacksID(item);
236-
item.screen = HocComponent(item.screen, this._setCurrentRef(index, item.__id__), index);
235+
if (item.screen) {
236+
if (this.isClassCompoent(item.screen) && !item.screen.__HOCNAME__) {
237+
this._makeStacksID(item);
238+
item.screen = HocComponent(item.screen, this._setCurrentRef(index, item.__id__));
239+
} else {
240+
this._makeStacksID(item);
241+
triggerOnce(item.screen, this._setCurrentRef(index, item.__id__));
242+
}
237243
}
238244
return item;
239245
})
@@ -287,12 +293,11 @@ export default class ScrollableTabView extends React.Component {
287293
*/
288294
_scrollTo = y => {
289295
if (typeof y == 'number') {
290-
this.section &&
291-
this.section.scrollToLocation &&
292-
this.section.scrollToLocation({
293-
itemIndex: 0,
294-
viewOffset: 0 - y
295-
});
296+
this.section?.scrollToLocation({
297+
itemIndex: 0,
298+
viewOffset: 0 - y,
299+
sectionIndex: 0
300+
});
296301
}
297302
};
298303

@@ -320,14 +325,24 @@ export default class ScrollableTabView extends React.Component {
320325
this.setState({});
321326
};
322327

323-
_getProps(props) {
328+
_getProps(props, screen) {
324329
return Object.assign(
325330
{
326331
refresh: this._refresh,
327332
scrollTo: this._scrollTo,
328333
toTabView: this.toTabView,
329334
layoutHeight: this.layoutHeight
330335
},
336+
!!screen && {
337+
initScreen: () => initScreen(screen),
338+
onRefresh: callback => {
339+
if (!screen.onRefresh) {
340+
screen.onRefresh = () => callback(this._toggledRefreshing);
341+
}
342+
onRefresh(screen, callback);
343+
},
344+
onEndReached: callback => onEndReached(screen, callback)
345+
},
331346
props || {}
332347
);
333348
}
@@ -337,7 +352,7 @@ export default class ScrollableTabView extends React.Component {
337352
const ref = this.getCurrentRef();
338353
if (stacks && stacks.sticky && typeof stacks.sticky == 'function' && ref && stacks.__id__ === ref.__id__) {
339354
// 用于自动同步 Screen 数据流改变后仅会 render 自身 Screen 的问题,用于自动同步 screenContext 给吸顶组件
340-
if (this.props.syncToSticky && !ref.__isOverride__) {
355+
if (this.props.syncToSticky && !ref.__isOverride__ && this.isClassCompoent(ref.constructor)) {
341356
const originalDidUpdate = ref.componentDidUpdate,
342357
context = this;
343358
ref.componentDidUpdate = function () {
@@ -437,7 +452,7 @@ export default class ScrollableTabView extends React.Component {
437452
return <Animated.View style={[styles.tabUnderlineStyle, _tabUnderlineStyle, interpolateAnimated]}></Animated.View>;
438453
}
439454

440-
_displayConsole(message, level = CONSOLE_LEVEL.WARN) {
455+
_displayConsole(message, level = CONSOLE_LEVEL.LOG) {
441456
const { errorToThrow } = this.props;
442457
const pluginName = packagejson.name;
443458
const msg = `${pluginName}: ${message || ' --- '}`;
@@ -569,6 +584,10 @@ export default class ScrollableTabView extends React.Component {
569584
return this.layoutHeight['container'] - this.layoutHeight['stickyHeader'] - this.layoutHeight['tabs'];
570585
}
571586

587+
isClassCompoent(component) {
588+
return !!(component.prototype && component.prototype.isReactComponent);
589+
}
590+
572591
_renderItem({ item, index }) {
573592
const { enableCachePage, fillScreen, fixedTabs, mappingProps } = this.props;
574593
const screenHeight = this._getScreenHeight();
@@ -585,7 +604,7 @@ export default class ScrollableTabView extends React.Component {
585604
!enableCachePage && this.state.checkedIndex == index && { minHeight: screenHeight }
586605
]}
587606
>
588-
<item.screen {...this._getProps(mappingProps)} {...(item.toProps || {})} />
607+
<item.screen {...this._getProps(mappingProps, !this.isClassCompoent(item.screen) && item.screen)} {...(item.toProps || {})} />
589608
</View>
590609
)
591610
);
@@ -595,7 +614,7 @@ export default class ScrollableTabView extends React.Component {
595614
const next = () => {
596615
const ref = this.getCurrentRef();
597616
!ref && this._displayConsole(`The Screen Ref is lost when calling onEndReached. Please confirm whether the Stack is working properly.(index: ${this.state.checkedIndex})`);
598-
if (ref && ref.onEndReached && typeof ref.onEndReached === 'function') ref.onEndReached();
617+
!!ref && this.isClassCompoent(ref.constructor) ? ref && ref.onEndReached && typeof ref.onEndReached === 'function' && ref.onEndReached() : triggerEndReached(ref);
599618
};
600619
if (this.state.checkedIndex != null) {
601620
const { onBeforeEndReached } = this.props;
@@ -613,7 +632,11 @@ export default class ScrollableTabView extends React.Component {
613632
const next = () => {
614633
const ref = this.getCurrentRef();
615634
!ref && this._displayConsole(`The Screen Ref is lost when calling onRefresh. Please confirm whether the Stack is working properly.(index: ${this.state.checkedIndex})`);
616-
ref ? ref.onRefresh && typeof ref.onRefresh === 'function' && ref.onRefresh(this._toggledRefreshing) : this._toggledRefreshing(false);
635+
if (ref) {
636+
this.isClassCompoent(ref.constructor) ? ref.onRefresh && typeof ref.onRefresh === 'function' && ref.onRefresh(this._toggledRefreshing) : triggerRefresh(ref, this._toggledRefreshing);
637+
} else {
638+
this._toggledRefreshing(false);
639+
}
617640
};
618641
const { onBeforeRefresh } = this.props;
619642
onBeforeRefresh && typeof onBeforeRefresh === 'function' ? onBeforeRefresh(next, this._toggledRefreshing) : next();
@@ -676,7 +699,8 @@ export default class ScrollableTabView extends React.Component {
676699

677700
_refreshControl() {
678701
const ref = this.getCurrentRef();
679-
return <RefreshControl enabled={!!(ref && ref.onRefresh)} refreshing={this.state.isRefreshing} onRefresh={this._onRefresh} />;
702+
const enabled = !!(ref && ref.onRefresh) || refreshMap.has(ref);
703+
return <RefreshControl enabled={enabled} refreshing={this.state.isRefreshing} onRefresh={this._onRefresh} />;
680704
}
681705

682706
_onScroll2Vertical(event) {
@@ -740,7 +764,6 @@ export default class ScrollableTabView extends React.Component {
740764
renderItem={() => {
741765
return (
742766
<AnimatedCarousel
743-
ref={c => (this.tabview = c)}
744767
pagingEnabled={true}
745768
inactiveSlideOpacity={1}
746769
inactiveSlideScale={1}
@@ -749,7 +772,6 @@ export default class ScrollableTabView extends React.Component {
749772
sliderWidth={deviceWidth}
750773
itemWidth={deviceWidth}
751774
onScrollIndexChanged={this._throttleCallback}
752-
initialScrollIndex={this.state.checkedIndex}
753775
firstItem={this.state.checkedIndex}
754776
onScroll={this._onScrollHandler2Horizontal}
755777
{...carouselProps}

0 commit comments

Comments
 (0)