ptomasroos / react-native-scrollable-tab-view

Tabbed navigation that you can swipe between, each tab can have its own ScrollView and maintain its own scroll position between swipes. Pleasantly animated. Customizable tab bar
https://www.npmjs.com/package/react-native-scrollable-tab-view
6.94k stars 2.28k forks source link

undefined is not an object (evaluating 'this.tabIcons.forEach') #244

Closed KGALLET closed 8 years ago

KGALLET commented 8 years ago

Hello,

I've got an issue while trying to use a CustomBar with my ScrollableTabView component.

Here is my code : CustomTabBar

constructor(props) {
    super(props)
    this.tabIcons = []
  }

  componentDidMount() {
     ...
  }

  setAnimationValue({ value, }) {
    this.tabIcons.forEach((icon, i) => {
      const progress = (value - i >= 0 && value - i <= 1) ? value - i : 1
      icon.setNativeProps({
        style: {
          color: this.iconColor(progress),
        },
      })
    })
  }

  // color between rgb(59,89,152) and rgb(204,204,204)
  iconColor(progress) {
    ...
  }

  render() {
      ...

    return (
      <View>
      <View style={ [styles.tabs, this.props.style] }>
        { this.props.tabs.map((tab, i) => {
          return (
          <TouchableOpacity
            key={ tab }
            onPress={ () => this.props.goToPage(i) }
            style={ styles.tab }
          >
            <Icon
              name={ tab }
              size={ 30 }
              color={ this.props.activeTab === i ? 'rgb(59,89,152)' : 'rgb(204,204,204)' }
              ref={ (icon) => { this.tabIcons[i] = icon } }
            />
          </TouchableOpacity>
      )}) }
      </View>
      <Animated.View style={ [styles.tabUnderlineStyle, { width: tabWidth }, { left, }] } />
    </View>
    )
  }
}

Toolbar.android.js

export default class Toolbar extends Component {
  render() {
    return (
      <View style={ styles.container }>
        <ScrollableTabView
          initialPage={ 0 }
          renderTabBar={ () => <CustomTabBar /> }
        >
         <ScrollView tabLabel="home">
           <Home />
         </ScrollView>
         <ScrollView tabLabel="map">
           <MapView />
         </ScrollView>
         <ScrollView tabLabel="pin">
           <Pin />
         </ScrollView>
         <ScrollView tabLabel="add-user">
          <Friends />
         </ScrollView>
       </ScrollableTabView>
      </View>
     )
  }
}

I used the code from FacebookTabBarExample that's why i put '...' .

I got the error : undefined is not an object (evaluating 'this.tabIcons.forEach') for the setAnimationValue method. I don't know how to solve this, if someone know what's my problem here, it would be nice to help me.

thank's

skv-headless commented 8 years ago

console.log(this) inside setAnimationValue. where setAnimationValue called? put debugger there and inside repl you will easily find out a problem.

KGALLET commented 8 years ago

setAnimationValue is called in componentDidMount, see here :

componentDidMount() {
    this.setAnimationValue({ value: this.props.activeTab })
    this._listener = this.props.scrollValue.addListener(this.setAnimationValue)
  }

Here is my debugger, as you can see my tabIcons array is not empty and not undefined capture d ecran 2016-04-19 a 14 44 58

vincentfretin commented 8 years ago

I'm pretty sure you need this.setAnimationValue.bind(this) when you use ES6 class. React.createClass do the binding of all methods for you.

The code should be:

componentDidMount() {
    this.setAnimationValue({ value: this.props.activeTab })
    this._listener = this.props.scrollValue.addListener(this.setAnimationValue.bind(this))
  }
KGALLET commented 8 years ago

@vincentfretin thx