2

I'm fairly new to react native and working on an app where I use a RkButton and then update the state when the button is clicked. The code is like this.

render() {
    const { user } = this.props;

    let navigate = this.props.navigation.navigate;

    let items = MainRoutes.map(function (route, index) {
      return (
        <RkButton
          rkType='square'
          key={index}
          onPress={() => {
              this.setState({
                redeem: true
              });
          }}>
        </RkButton>
      )
    });

      return (
        <View style={{flex: 1,}}>
            <ScrollView
              alwaysBounceVertical
              overScrollMode={"always"}
              style={{flex: 1, backgroundColor: 'white'}}
              refreshControl={
                  <RefreshControl
                  refreshing={this.state.refreshing}
                  onRefresh={() => this.handleRefresh()}
                  />
              }
              contentContainerStyle={styles.rootContainer}>
                {items}
            </ScrollView>
          </View>
      )
}

I get 'this.setState is not a function', since I've used the code from the UIKitten library I'm not entirely familiar with it. I'm pretty sure this is something to do with either ES6 or a misunderstanding on my part of how components work.

Could someone enlighten me?

SwimmingG
  • 654
  • 2
  • 9
  • 29
  • 1
    Possible duplicate of [React 'cannot read property of undefined' when using map](https://stackoverflow.com/questions/45010544/react-cannot-read-property-of-undefined-when-using-map/45010580#45010580) – Shubham Khatri Apr 15 '18 at 09:58

3 Answers3

3

You loose the Components context here:

  // Component context
  function (route, index) {
    // Functions context

Change it to:

  (route, index) => {
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • Aha! Ok, thanks! Is there any time you would want to lose the scope? Is it just for encapsulation? – SwimmingG Apr 15 '18 at 09:52
  • @swimmingG you might want to loose the *context* (sorry for the confusion), for example in handlers when you want to refer to the clicked element. E.g. in jquery `$("a").click(function(){ $(this) /*!!*/ })` – Jonas Wilms Apr 15 '18 at 09:54
  • Ah ok, so `this` when you use function (route, index) is then the button that was clicked. Thanks! – SwimmingG Apr 15 '18 at 09:55
  • @swimmiG in this case it would probably be `window`, which is not really useful – Jonas Wilms Apr 15 '18 at 09:56
2

The problem is that function declared with keyword function have it own context this. You need to use arrow functions to have access to parent context:

let items = MainRoutes.map((route, index) => {
  return (
    <RkButton
      rkType='square'
      key={index}
      onPress={() => {
          this.setState({
            redeem: true
          });
      }}>
    </RkButton>
  )
});
Artem Mirchenko
  • 2,140
  • 1
  • 9
  • 21
0

You should keep a copy of this and use it inside any other function. whenever needed, as mention in line number 3.

so your code has some minor change

render() {
    const { user } = this.props;
    let self=this;

    let navigate = this.props.navigation.navigate;

    let items = MainRoutes.map(function (route, index) {
      return (
        <RkButton
          rkType='square'
          key={index}
          onPress={() => {
              self.setState({
                redeem: true
              });
          }}>
        </RkButton>
      )
    });

      return (
        <View style={{flex: 1,}}>
            <ScrollView
              alwaysBounceVertical
              overScrollMode={"always"}
              style={{flex: 1, backgroundColor: 'white'}}
              refreshControl={
                  <RefreshControl
                  refreshing={this.state.refreshing}
                  onRefresh={() => this.handleRefresh()}
                  />
              }
              contentContainerStyle={styles.rootContainer}>
                {items}
            </ScrollView>
          </View>
      )
}
RANVIR GORAI
  • 1,226
  • 11
  • 10