0

I am using a map function and have tested and confirmed that within the maps function this is referencing the class object as desired.

When I try passing this again by binding it to a jsx function, it doesn't pass this as desired.

Error: Uncaught TypeError: _this3.checkType(...).bind is not a function

// wrapped in a class

checkType(type, options, placeholder, name, handleUpdatedValue, defvalue, index) {

        console.log(this);

        switch(type) {
            case 'select':
                return <select onChange={handleUpdatedValue.bind(this)} >{options.map((option, i) => <option value={option} key={i}>{option}</option>)}</select>
                break;
            case 'text':
                return <input onChange={handleUpdatedValue.bind(this)} name={name} placeholder={placeholder} type="text" />
                break;
            case 'date':
                return <input onChange={handleUpdatedValue.bind(this)} name={name} placeholder={placeholder} type="date" />
                break;
            default: 
                console.log('Error: Invalid Type');
        }
        return type === 'select' ? <select></select> : <input />
    }

return(
        <div className="formwrapper thinshadow">    
            <h3>{this.props.header}</h3>
            {this.getFields().map((field, i) => {
                <div key={i} className={field.classes}>
                    {this.checkType(field.type, field.options, field.placeholder, field.name, this.handleUpdatedValue.bind(this), field.defvalue, field.index).bind(this)}

                                                                  // DOES NOT WORK ^

                    <div className="minilabel"></div>
                </div>
            }, this)}                                         // THIS WORKS

            <button className="btn btn-primary" 
                    onClick={() => this.props.onClick(values)} >
                    Save
            </button>
        </div>  
    );
Sequential
  • 1,455
  • 2
  • 17
  • 27

1 Answers1

3

You are invoking the function instead of binding it.

this.checkType(field.type, field.options, field.placeholder, field.name, this.handleUpdatedValue.bind(this), field.defvalue, field.index).bind(this)

should be

this.checkType.bind(this, field.type, field.options, field.placeholder, field.name, this.handleUpdatedValue.bind(this), field.defvalue, field.index)

bind Usage

fun.bind(thisArg[, arg1[, arg2[, ...]]]

Refer to this link for more details:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Edit

You use bind when you are passing your function to another context (another this pretty much), and still want the function to be invoked under the original this.

In your situation, you don't need to bind because within your map, you have the same this. See You Don't Need to Bind This in React when using forEach and map.

But if you do want to, I strongly advise against binding when you are iterating. You can use closure, and bind before the iteration.

bind is slow, even though it doesn't really matter most of the time. But more importantly, you don't want to bind in iterations like forEach or map because it's easy to lose the context (this) without knowing (when you are not using React). And you will scratch you head for a few hours.

If you are using React, you can bind in the render function.

render: () {
  const checkType = this.checkType.bind(this);
  render (
    map((node) => { checkType(...) });
  );
}
Community
  • 1
  • 1
Edmund Lee
  • 2,514
  • 20
  • 29
  • I am trying to invoke it while maintaining this. The functions purpose is to return the correct field. If I do the .bind, it removes the error, but does not invoke the function. I am new at this so please excuse me if I don't understand your solution. Nevermind, just saw your link, thank you! – Sequential Jan 25 '17 at 18:44
  • @Sequential You can simply call `this.checkType(...)`. I will add an edit for more details. – Edmund Lee Jan 25 '17 at 18:47