buydadip
buydadip

Reputation: 9417

How to use parent function inside react's map function

I'm passing the following functions to the following component...

<Main css={this.props.css} select={this.selectedCSS.bind(this)} save={this.saveCSS.bind(this)} />

Then inside the Main component I am using these functions...

<h1>Select the stylesheet you wish to clean</h1>
{
    this.props.css.map(function(style){

        if (style) {
            return (<div className="inputWrap"><input type="radio" name="style_name" onClick={this.props.select(style)}/><span></span><a key={style}>{style}</a></div>)
                }
            })
        }

        </div>
        <button className="cleanBtn" onClick={this.props.save}>Clean!</button>

Notice in my map function, I am passing this.props.select(style). This is a function from the parent, and I am trying to pass to it a parameter. But when I do this, I get an error...

Error in event handler for runtime.onMessage: TypeError: Cannot read property 'props' of undefined

Every other function I pass works. I've already tested them. In fact, the code works, the only issue is when I try to pass a function inside map. What is the reason for this? How can I fix it?

I tried to add .bind(this) but it runs in an infinite loop when I do so.

Upvotes: 0

Views: 1570

Answers (3)

yadhu
yadhu

Reputation: 15632

The problem is that Array.prototype.map doesn't bind a this context unless explicitly told to.

this.props.css.map(function(style) {
  ...
}, this) // binding this explicitly

OR

this.props.css.map((style) => { // arrow function
  ...
})

OR

const self = this;
this.props.css.map((style) => {
  ... // access 'self.props.select'
})

I also see another problem with your code. Inside map you're doing this

if (style) {
    return (
        <div className="inputWrap">
            <input type="radio" name="style_name" onClick={this.props.select(style)}/>
            <span>something</span>
            <a key={style}>{style}</a>
        </div>
    );       
}

Here input element is expecting a function for its onClick, but you're actually evaluating the function by calling this.props.select(style) and passing its return value (if at all it returns something) to onClick. Instead you may need to do this:

this.props.css.map((style) => {
    if (style) {
        return (
            <div className="inputWrap">
                <input type="radio" name="style_name" onClick={() => this.props.select(style)}/>
                <span>something</span>
                <a key={style}>{style}</a>
            </div>
        );       
    }
})

Upvotes: 3

Mark Williams
Mark Williams

Reputation: 2308

You mentioned passing a parameter when calling a parent's function? As onClick wants a reference to a function (but realising that you need to pass a parameter), you could try the following:

onClick={() => { this.props.select(style) }}

Upvotes: 0

TimoStaudinger
TimoStaudinger

Reputation: 42450

In your mapping function, this does no longer point to the react component.

Bind the context manually to resolve this:

{
    this.props.css.map((function(style) {
        if (style) {
            return (<div className="inputWrap"><input type="radio" name="style_name" onClick={this.props.select(style)}/><span></span><a key={style}>{style}</a></div>)
        }
    }).bind(this))
}

Alternatively, use an ES6 arrow function, which preserves the surrounding context:

{
    this.props.css.map(style => {
        if (style) {
            return (<div className="inputWrap"><input type="radio" name="style_name" onClick={this.props.select(style)}/><span></span><a key={style}>{style}</a></div>)
        }
    })
}

Upvotes: 2

Related Questions