Skip to content

Commit 755caea

Browse files
haoliangwugoldenyz
andauthored
feat: add onSync callback to resolve #87 (#91)
* feat: add onSync callback to resolve #87 * fix: should keep updateScroll as manual trigger api * doc: update the README * simplify code Co-authored-by: Allen Yang <Goldenyz@hotmail.com>
1 parent b208ee5 commit 755caea

File tree

3 files changed

+61
-20
lines changed

3 files changed

+61
-20
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ All the callback 'onXXXX' can accept a parameter: the ref to the scrollbar conta
7979
</PerfectScrollbar>
8080
```
8181

82+
#### onSync
83+
Invoked when `PerfectScrollbar` comp needs to sync the scrollbar container by invoking `ps.update()`(Basically, it is invoked in CDU lifecycle) and receive the internal `perfect-scroll` instance `ps` as parameter.
84+
85+
It is useful when you want to customize the sync logic in some scenarios, eg: debounce the invocation of `ps.update()`.
86+
87+
For more detail, please refer to [issue#87](https://github.com/goldenyz/react-perfect-scrollbar/issues/87) and the example directory.
88+
8289
#### React.HTMLAttributes
8390
Any attributes defined in [React.HTMLAttributes](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L1689) can be used for the component.
8491

example/example.js

+47-18
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,22 @@ function logEvent(type) {
1010
console.log(`event '${type}' triggered!`);
1111
}
1212

13+
const debounce = (fn, ms = 0) => {
14+
let timeoutId;
15+
return function wrapper(...args) {
16+
clearTimeout(timeoutId);
17+
timeoutId = setTimeout(() => fn.apply(this, args), ms);
18+
};
19+
};
20+
1321
class Example extends Component {
1422
constructor(props) {
1523
super(props);
1624

1725
this.state = {
1826
className: undefined,
1927
onXReachEnd: null,
28+
items: Array.from(new Array(100).keys()),
2029
};
2130
}
2231

@@ -33,28 +42,48 @@ class Example extends Component {
3342
logEvent('onYReachEnd');
3443
}
3544

45+
handleTrigger = () => {
46+
this.setState({
47+
items: Array.from(new Array(100).keys()),
48+
});
49+
}
50+
51+
handleSync = debounce((ps) => {
52+
ps.update();
53+
console.log('debounce sync ps container in 1000ms');
54+
}, 1000)
55+
3656
render() {
3757
const { className, onXReachEnd } = this.state;
3858

3959
return (
40-
<div className="example">
41-
<ScrollBar
42-
className={className}
43-
onScrollY={() => logEvent('onScrollY')}
44-
onScrollX={() => logEvent('onScrollX')}
45-
onScrollUp={() => logEvent('onScrollUp')}
46-
onScrollDown={() => logEvent('onScrollDown')}
47-
onScrollLeft={() => logEvent('onScrollLeft')}
48-
onScrollRight={() => logEvent('onScrollRight')}
49-
onYReachStart={() => logEvent('onYReachStart')}
50-
onYReachEnd={this.handleYReachEnd}
51-
onXReachStart={() => logEvent('onXReachStart')}
52-
onXReachEnd={onXReachEnd}
53-
component="div"
54-
>
55-
<div className="content" />
56-
</ScrollBar>
57-
</div>
60+
<React.Fragment>
61+
62+
<div className="example">
63+
<ScrollBar
64+
className={className}
65+
onScrollY={() => logEvent('onScrollY')}
66+
onScrollX={() => logEvent('onScrollX')}
67+
onScrollUp={() => logEvent('onScrollUp')}
68+
onScrollDown={() => logEvent('onScrollDown')}
69+
onScrollLeft={() => logEvent('onScrollLeft')}
70+
onScrollRight={() => logEvent('onScrollRight')}
71+
onYReachStart={() => logEvent('onYReachStart')}
72+
onYReachEnd={this.handleYReachEnd}
73+
onXReachStart={() => logEvent('onXReachStart')}
74+
onXReachEnd={onXReachEnd}
75+
component="div"
76+
>
77+
<div className="content" />
78+
</ScrollBar>
79+
</div>
80+
<div className="example">
81+
<button onClick={this.handleTrigger}>Trigger</button>
82+
<ScrollBar onSync={this.handleSync}>
83+
{this.state.items.map(e => (<div key={e}>{e}</div>))}
84+
</ScrollBar>
85+
</div>
86+
</React.Fragment>
5887
);
5988
}
6089
}

src/scrollbar.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ export default class ScrollBar extends Component {
3737

3838
componentDidUpdate(prevProps) {
3939
this._updateEventHook(prevProps);
40-
this._ps.update();
40+
41+
this.updateScroll();
42+
4143
if (prevProps.className !== this.props.className) {
4244
this._updateClassName();
4345
}
@@ -90,7 +92,7 @@ export default class ScrollBar extends Component {
9092
}
9193

9294
updateScroll() {
93-
this._ps.update();
95+
this.props.onSync(this._ps);
9496
}
9597

9698
handleRef(ref) {
@@ -116,6 +118,7 @@ export default class ScrollBar extends Component {
116118
onXReachStart,
117119
onXReachEnd,
118120
component,
121+
onSync,
119122
children,
120123
...remainProps
121124
} = this.props;
@@ -145,6 +148,7 @@ ScrollBar.defaultProps = {
145148
onYReachEnd: undefined,
146149
onXReachStart: undefined,
147150
onXReachEnd: undefined,
151+
onSync: ps => ps.update(),
148152
component: 'div',
149153
};
150154

@@ -165,5 +169,6 @@ ScrollBar.propTypes = {
165169
onYReachEnd: PropTypes.func,
166170
onXReachStart: PropTypes.func,
167171
onXReachEnd: PropTypes.func,
172+
onSync: PropTypes.func,
168173
component: PropTypes.string,
169174
};

0 commit comments

Comments
 (0)