0

What I have is a list of items, where each of the Item Component have a delete button that will make a call to the deleteItem function in the List component to update its state. The deleteItem function will need the parent instance bound to it to call this.setState.

Currently I'm passing parent={this} along with deleteHandler={this.deleteItem} when the List renders the Item. So that when the Item calls the handler, it will have access to the parent instance.

onClick={this.props.deleteHandler.bind(
    this.props.parent,
    this.props._key
)}

But this feels unnecessary, and I'm wondering if there's a better way to achieve what I want to do. (ie. some kind of built in linkage between child and parents, or a better way to pass/call the function)

codepen

Child Component

class Item extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <li>
                {this.props.value}
                <button
                    className="delete"
                    onClick={this.props.deleteHandler.bind(
                        this.props.parent,
                        this.props._key
                    )}
                >
                    x
                </button>
            </li>
        );
    }
}

Parent Component

class List extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            items: []
        };
    }
    renderItem(item) {
        return (
            <Item
                key={item.key}
                value={item.value}
                _key={item.key}
                deleteHandler={this.deleteItem}
                parent={this}
            />
        );
    }
    addItem() {
        // ...
    }
    deleteItem(key) {
        this.setState(prevState => ({
            items: prevState.items.filter(function(obj) {
                return obj.key !== key;
            })
        }));
    }
    render() {
        var items = [];
        for (var i = 0; i < this.state.items.length; i++) {
            items.push(this.renderItem(this.state.items[i]));
        }
        return (
            <React.Fragment>
                <ul>{items}</ul>
                <button className="addItem" onClick={this.addItem.bind(this)}>
                    Add Value
                </button>
            </React.Fragment>
        );
    }
}

Thanks!

Iceandele
  • 630
  • 1
  • 8
  • 25
  • 1
    Instead of passing your entire parent instance to the `Item` component, you could pass a function that the child will call to remove itself in the parent. – Tholle Jul 18 '18 at 16:30
  • @Tholle I am passing the function to the child with deleteHandler=deleteItem. But how do I call that function? If I just call it normally, this.setState won't be defined as this will refer to window. – Iceandele Jul 18 '18 at 16:36
  • 1
    You could bind it in the constructor with `this.deleteItem = this.deleteItem.bind(this);` or make `deleteItem` into an arrow function with `deleteItem = () => { ... };` – Tholle Jul 18 '18 at 16:38
  • 1
    Ahh yes that does the trick. It looks like i was a little confused about the functionality of `bind` and wasn't too familiar with the specifics of the arrow notation. thanks! – Iceandele Jul 18 '18 at 16:49

0 Answers0