Joel Hager
Joel Hager

Reputation: 3440

How to pass a function reference to a child component while also using the state of the parent component?

I'm not sure exactly how to word this, so I'll do some pseudo code to illustrate:

I have a main component that has a map function that is iterating over an array of values. Inside the map function is a functional prop that references a handler function. I want to be able to not only return a value from the onClick, but I need to access variables that are still inside the mapped instance of the component.

parent
[1,2,3].map(num => ( <child funcProp={handleClick} )

in child:
const {funcProp} = props
---code that does calc or state
funcProp(res)

I'm getting the result I want from the child component, but I need a parameter from the invoking map as well. So for instance, I'd want (if we're at number 2 in the map) I want to return the res from the child component with the num 2 for the handler function. I'm sure there's some syntax that I am forgetting.

Upvotes: 0

Views: 679

Answers (3)

sdgluck
sdgluck

Reputation: 27237

The rules of closures still apply in React. Create an anonymous function that calls handleClick itself. This function will have access to the map callback arguments:

[1,2,3].map((num) => {
  return <child funcProp={() => handleClick(num)} />
})

Note that with this pattern, handleClick will no longer receive arguments from a call to funcProp in the child component. If you still want handleClick to receive these arguments, you must pass them along explicitly:

[1,2,3].map((num) => {
  return <child funcProp={(...args) => handleClick(num, ...args)} />
})

Or, if you want num to be the last argument to handleClick:

[1,2,3].map((num) => {
  return <child funcProp={(...args) => handleClick(...args.concat(num))} />
})

You could avoid the anonymous function though, and make use of Function.prototype.bind to create a bound copy of handleClick with a fixed first argument of num:

[1,2,3].map((num) => {
  return <child funcProp={handleClick.bind(null, num)} />
})

In this case, we bind handleClick to the context null. This may or may not be appropriate for your use case - something to consider.

Upvotes: 1

Sofiya rao
Sofiya rao

Reputation: 86

In this case you might need to binding with "this" while passing the function.

If i use the example you mentioned then maybe this could help -

handleClick.bind(this)

Upvotes: 0

iunfixit
iunfixit

Reputation: 994

You can create a function which will let you access the value you want

[1,2,3].map(num => ( <child funcProp={() => handleClick(num)} )

Or pass the value in the child props as well

[1,2,3].map(num => ( <child num={num} funcProp={handleClick} )

Upvotes: 0

Related Questions