1

Im currently a little stuck with the following.

function Tag(props){
    let {text, onRemove, key} = props;
    return (
        <span onClick={onRemove(key)} key={key}>{text}</span>
    )
}

function TagInput (props) {
    let {onChange, value, onKeyDown} = props;
    return (
        <input type="text" onChange={onChange} value={value} onKeyDown={onKeyDown} />
    )
}

class TagsInput extends Component {
    render() {
        let { Tag, TagInput, state } = this.props;
        console.log(state.tags);
        return (
            <div ref="div" onClick={(e) => this.handleClick(e)}>
                {state.tags.map((tag) =>
                    <Tag
                        text={tag.text}
                        key={tag.id}
                        onRemove={this.handleRemove}
                    />
                )}
                <TagInput
                    onChange={(e) => this.handleChange(e)}
                    onKeyDown={(e) => this.handleKeyDown(e)}
                />
            </div>
        )
    }

    handleClick(e) {
        console.log(e.target.value);
    }

    handleChange(e){
        //console.log(e.target.value);
    }

    handleKeyDown(e){
        //console.log('keycode', e.keyCode);
        const { dispatch } = this.props;
        if (e.keyCode === 32) {
            dispatch(addTag(e.target.value));
        }
        if (e.keyCode === 8 && e.target.value.length === 0) {
            dispatch(removeTag());
        }
    }

    handleRemove(id){
        const { dispatch } = this.props;
        dispatch(removeTag(id));
    }
}

TagsInput.propTypes = {
    TagInput: React.PropTypes.func,
    Tag: React.PropTypes.func,
    removeKeyCodes: React.PropTypes.array,
    addKeyCodes: React.PropTypes.array
};

TagsInput.defaultProps = {
    TagInput: TagInput,
    Tag: Tag,
    removeKeyCodes: [8],
    addKeyCodes: [9, 13]
};

I get the following error in console Uncaught TypeError: Cannot read property 'props' of undefined from method handleRemove line const { dispatch } = this.props. It seems like a scoping issue but I cannot seem to understand why this (no pun intended lol) is occurring.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Deep
  • 2,988
  • 4
  • 34
  • 44

2 Answers2

1

Have you tried binding this? Try this.handleRemove.bind(this, tag.id). The tag.id there is the argument you're passing since handleRemove(id) needs an id as an arg.

oobgam
  • 1,309
  • 8
  • 10
1

ES6 classes do not automatically bind this to functions with the exception of the ones provided by extending Component such as componentDidMount etc..

from the docs

The ES6 way - bind this to your methods in your constructor, OR where you call them:

class TagsInput extends Component {
  constructor (props) {
    super(props)
    this.handleRremove = this.handleRemove.bind(this)
  }

  OR

  render() {
    return (
     <Tag   
       onRemove={this.handleRemove.bind(this)}
     />
  }

The ES7 way #1: bind syntax

this.handleRemove = ::this.handleRemove

The ES7 way #2: class arrow functions (I think this is the best way):

handleRemove = (id) => {
    const { dispatch } = this.props;
    dispatch(removeTag(id));
}

Then call it like:

onRemove={ () => this.handleRemove(tag.id) }

UPDATE: Read @Road's answer as well. When binding the method at point of use you need to pass the argument along.

azium
  • 20,056
  • 7
  • 57
  • 79