Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native Snap Carousel: Invariant Violation: inputRange must be monotonically increasing NaN,NaN,NaN

Tags:

react-native

I'm very new to React Native and I'm trying to use this component: https://github.com/archriss/react-native-snap-carousel

I tried using that code they provided in the usage portion to create the simplest working version:

    return (
        <Carousel
          ref={(c) => { this._carousel = c; }}
          data={this.state.entries} // this seems to be the problem
          renderItem={this._renderItem}
          sliderWidth='100%'
          itemWidth='80%'
        />
    );

Where "entries" is an array. This results in the following error:

Invariant Violation: inputRange must be monotonically increasing NaN,NaN,NaN

Edit: Here's the _renderItem method

_renderItem ({item, index}) {
    return (
        <View style={styles.slide}>
            <Text style={styles.title}>{ item.title }</Text>
        </View>
    );
  }
like image 524
Randy Huynh Avatar asked Dec 22 '17 07:12

Randy Huynh


2 Answers

If you dig in further into react-native source code, you can find the error source in file AnimatedInterpolation.js where it expects inputRange for interpolation to be an array of numbers. So my best guess is react-native-snap-carousel uses itemWidth value to calculate interpolation's data and pass it to react-native's Animated component. You can find that implementation in here. If you provide a non-integer value to itemWidth, the calculation will always return NaN, creating that error.

Short answer: replace itemWidth with a actual number.

UPDATE 16 Jan 2020: newer version of react-native changes the message, so I updated the links accordingly and added original code:

Handler inside AnimatedInterpolation.js (react-native v0.61.5)

function checkValidInputRange(arr: Array<number>) {
  invariant(arr.length >= 2, 'inputRange must have at least 2 elements');
  for (let i = 1; i < arr.length; ++i) {
    invariant(
      arr[i] >= arr[i - 1],
      /* $FlowFixMe(>=0.13.0) - In the addition expression below this comment,
       * one or both of the operands may be something that doesn't cleanly
       * convert to a string, like undefined, null, and object, etc. If you really
       * mean this implicit string conversion, you can do something like
       * String(myThing)
       */
      'inputRange must be monotonically non-decreasing ' + arr,
    );
  }
}

Function using sliderWidth and pass to inputRange in react-native-snap-carousel (v3.8.4)

_initPositionsAndInterpolators (props = this.props) {
        const { data, itemWidth, itemHeight, vertical } = props;
        const sizeRef = vertical ? itemHeight : itemWidth; // USAGE

        // ...

        this._getCustomData(props).forEach((itemData, index) => {
            const _index = this._getCustomIndex(index, props);
            const start = (_index - 1) * sizeRef;          // HERE
            const middle = _index * sizeRef;               // HERE
            const end = (_index + 1) * sizeRef;            // AND HERE
            const animatedValue = this._shouldAnimateSlides(props) ? this._scrollPos.interpolate({
                inputRange: [start, middle, end],
                outputRange: [0, 1, 0],
                extrapolate: 'clamp'
            }) : 1;

            this._positions[index] = {
                start: index * sizeRef,
                end: index * sizeRef + sizeRef
            };

            interpolators.push(animatedValue);
        });

        this.setState({ interpolators });
    }
like image 89
blaz Avatar answered Oct 20 '22 12:10

blaz


I had the same issue and I solved by simply setting itemHeight as well.. It might also be that the issue comes from you trying to specify the width and height as a relative size to the screen, and it may only take a number..

return (
    <Carousel
      data={this.state.entries}
      renderItem={this._renderItem}
      sliderWidth={sliderWidth}
      itemWidth={sliderWidth}
      itemHeight={itemHeight}
    />
);
const sliderWidth = Dimensions.get('window').width;
const itemHeight = Dimensions.get('window').height;
like image 6
Philip Johan Brun Avatar answered Oct 20 '22 14:10

Philip Johan Brun