1

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.

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Couldn't you also use a fat arrow function and call the method within said function?
This worked. But why did THIS work but binding in the constructor did not?
@MichaelLyons Sure; you could also bind it.
1

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))}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.