FrenchMajesty
FrenchMajesty

Reputation: 1159

React Native this2.'function' is not a function

I have a problem with my React Native Component.

sayHi = (s) => {
    console.log('hey' + s)
}

renderListItem(item, i) {

    return (
        <TouchableOpacity
            key={i}
            style={styles.listItem}
            onPress={() => { this.sayHi('bob') }}>

        <Text>{item}</Text>
        </TouchableOpacity>
    )
}

render() {
    this.sayHi('patrick')

    const { list } = this.props

    return (
        <View>
        {list.map(this.renderListItem)}
        </View>
    )
}

In renderListItem I get an error _this2.sayHi is not a function.

Searched online but most posts do not fit my situation; I took a look at this post but I already have an arrow function so it's not a context problem.

The function console logs just fine in the render(). I tried to bind the this in the constructor but I still get the error.

Upvotes: 1

Views: 4006

Answers (2)

Andrew Li
Andrew Li

Reputation: 57982

Array#map executes the callback in a different context so this isn't correctly bound. Per the documentation:

Syntax

var new_array = arr.map(callback[, thisArg])

Parameters

[...]

thisArg

Optional. Value to use as this when executing callback.

[...]

If a thisArg parameter is provided to map, it will be used as callback's this value. Otherwise, the value undefined will be used as its this value.

You can pass this context as the second argument to Array#map:

{list.map(this.renderListItem, this)}

Or, use Function#bind directly:

{list.map(this.renderListItem.bind(this))}

Finally, you could use an arrow function:

{list.map((item, i) => this.renderListItem(item, i))}

Though I would choose the first option personally.

Upvotes: 5

speckledcarp
speckledcarp

Reputation: 6375

Just for reference, the bind solution mentioned in the comments by Andrew Li can be accomplished by changing this line

{list.map(this.renderListItem)}

to this

{list.map(this.renderListItem.bind(this))}

Upvotes: 1

Related Questions