0

So I am having some trouble combining concepts of .map() and function binding. I am using .map() in the same way ngFor is used in angular, to place a custom button component on the page for every item in a user's account.

Here is some example code:

class MyButton extends Component {
  constructor(props) {
    super();
    this.state = {
      progress: 0
    }
  }

  render() {
    return(
      <TouchableWithoutFeedback onPress={this.pressFunction}>
        (...more code inside)
      </TouchableWithoutFeedback>
    )
  }

  pressFunction = () => {
    (animate progress from 0 to 1 for some animation)
  }
}

/////////////////////////////////////////////////////////////////

class Parent extends Component {
  render() {
    return(
      {
        this.props.data.array.map(obj => {
          return(
            <View style={someStyle}>
              <MyButton data={obj} />
            </View>
          )
        })
      }
    )
  }
}

So in the Parent Component, multiple MyButtons are rendered properly, each according to the passed object from the array. However, when any button is pressed, all of the pressFunctions for all MyButtons fire.

My question is I guess, how do I ensure that each pressFunction of each MyButton is bound only to the specific instance of the MyButton? I am having trouble with the scope here.

My understanding is that

functionName = () => {}

should properly bind the function to the instance, but I have tried the older ways as well with the same result.

6
  • "However, when any button is pressed, all of the pressFunctions for all MyButtons fire." Why do you think like that? Commented Aug 28, 2018 at 20:44
  • should properly bind the function to the instance, but I have tried the older ways as well with the same result - this means that the problem isn't related to binding to wrong instance, doesn't it? Commented Aug 28, 2018 at 21:11
  • devserkan not sure about what you mean haha. estus, I am not sure, that is why I am asking. I cannot think what other issues might cause this problem unless there is something I am missing with the scope Commented Aug 28, 2018 at 21:33
  • I am hoping maybe someone has crossed this issue and solved it themselves before Commented Aug 28, 2018 at 21:34
  • You are saying when you press any button all of the pressFunctions fires. How? This is not normal. Each component instance owns its function here. Commented Aug 28, 2018 at 21:47

2 Answers 2

1

I solved this by creating a dynamic ref on each object mapped to a MyButton, using a unique property of each obj in the array:

this.props.data.array.map(obj => {
  return(
    <View style={someStyle}>
      <MyButton ref={obj.name} data={obj} />
    </View>
  )
})

Still don't know why my it didn't bind uniquely without a ref

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

Comments

0

You should pass onPress as a props. Below is the updated code

class MyButton extends Component {
  constructor(props) {
    super();
    this.state = {
      progress: 0
    }
  }

  render() {
    return(
      <TouchableWithoutFeedback onPress={this.props.onPress}>
        (...more code inside)
      </TouchableWithoutFeedback>
    )
  }
}

/////////////////////////////////////////////////////////////////

class Parent extends Component {
  pressFunction = () => {
    (animate progress from 0 to 1 for some animation)
  }
  render() {
    return this.props.data.array.map(obj => {
      return(
        <View style={someStyle}>
          <MyButton 
            data={obj} 
            onPress={this.pressFunction}
          />
        </View>
      )
    })
  }
}

2 Comments

If I do that can I animated the state.progress of the individual buttons separately? Each MyButton has its own animation controlled by its own this.state.progress, and the pressFunction must be able to access this value
I am working on a solution to dynamically define a ref for each MyButton that is generated, but am not sure if that will work

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.