diff --git a/README.md b/README.md index f81248f..fbf80ef 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,10 @@ AppRegistry.registerComponent('swiper', () => swiper) | Prop | Default | Type | Description | | :------------ |:---------------:| :---------------:| :-----| -| index | `0` | `number` | Index number of initial slide. | +| index | | `number` | Show slide in this index. | +| initialIndex | `0` | `number` | Index number of initial slide. Not applicable with `index`.| | pager | `true` | `boolean` | Show pager. | -| onPageChange | | `function` | Callback when page changes. | +| onPageChange | | `function` | Callback when page changes or change is requested if `index` is set. | | activeDotColor | `blue` | `string` | CSS color of the dot for the current page. | diff --git a/src/index.js b/src/index.js index 7adda2d..359dd07 100644 --- a/src/index.js +++ b/src/index.js @@ -10,17 +10,20 @@ import React, { import Dots from './dots' +const hasValue = v => v != null; + export default class Swiper extends Component { static propTypes = { children: React.PropTypes.node.isRequired, index: React.PropTypes.number, + initialIndex: React.PropTypes.number, pager: React.PropTypes.bool, onPageChange: React.PropTypes.func, activeDotColor: React.PropTypes.string, } static defaultProps = { - index: 0, + initialIndex: 0, pager: true, onPageChange: () => {}, activeDotColor: 'blue', @@ -28,14 +31,23 @@ export default class Swiper extends Component { constructor(props) { super(props) + this.isControlled = hasValue(props.index); + var initial = this.isControlled ? props.index : props.initialIndex; this.state = { - index: props.index, - scrollValue: new Animated.Value(props.index), + index: initial, + scrollValue: new Animated.Value(initial), viewWidth: Dimensions.get('window').width, } } + componentWillReceiveProps(nextProps) { + if (this.isControlled && nextProps.index !== this.state.index) { + this.goToPage(nextProps.index); + clearTimeout(this.revertSwipeTimer); + } + } + componentWillMount() { const release = (e, gestureState) => { const relativeGestureDistance = gestureState.dx / this.state.viewWidth @@ -49,7 +61,18 @@ export default class Swiper extends Component { newIndex = newIndex - 1 } - this.goToPage(newIndex) + this.props.onPageChange(newIndex); + + if (this.isControlled) { + // If the parent does not update this.props.index within 50ms revert + // back to previous index. With 50ms we get nice bouncing effect. + this.revertSwipeTimer = setTimeout(() => { + this.goToPage(this.state.index); + }, 50); + } else { + this.goToPage(newIndex); + } + } this._panResponder = PanResponder.create({ @@ -75,6 +98,10 @@ export default class Swiper extends Component { }) } + componentWillUnmount() { + clearTimeout(this.revertSwipeTimer); + } + goToPage(pageNumber) { // Don't scroll outside the bounds of the screens pageNumber = Math.max(0, Math.min(pageNumber, this.props.children.length - 1)) @@ -83,8 +110,6 @@ export default class Swiper extends Component { }) Animated.spring(this.state.scrollValue, {toValue: pageNumber, friction: this.props.springFriction, tension: this.props.springTension}).start(); - - this.props.onPageChange(pageNumber) } handleLayout(event) {