Search code examples
javascriptreactjsobjectreact-componentreact-grid-layout

multiple instances of the component, trying to remove onclick - but always the last one is being removed


Here is simplified example of my code

 constructor(props) {
        super(props);
        this.state = {
            components:[ComponentA, ComponentA, ComponentA, ComponentA, ComponentA ]
        }
    }

 hide(i){
        let components= this.state.components.filter((item,k)=>k!=i);
        this.setState({components});
    }


 render() {
       return (<div>
            {this.state.components.map((item,i) => {
                    let ChildComponent = item;
                    return <div key={i} onClick={()=>this.hide(i)}>
                              <ChildComponent />
                           </div>
             })

 }

Here I have instances of the same component. When I click on one - I expect the div with this particular instance to be removed. To check that - here is my ComponentA code:

constructor(props) {
        super(props);
        this.state = {
             uid: Math.random()
        }
    }
    render() {
        return (
            <div>
                ComponentA - {this.state.uid}
            </div>
        );
    }

So each instance have its unique uid in state. When I click on one of the the components - always the last is one being removed.

enter image description here


UPDATE

That was simplified version, It's working now. My real problem was with react-grid-layout:

this.state = {
            testlayout: [
                {"w": 10,"h": 100,"i": 0,"x": 0, "y": 0,"widget": Component4},
                {"w": 10,"h": 100,"i":1,"x": 10, "y": 0,"widget": Component4},
                {"w": 10,"h": 100,"i": 2,"x": 20, "y": 0,"widget": Component4},
            ]
        }

onClose(i){
        let testlayout = this.state.testlayout.filter((item,k)=>item.i!=i);
        this.setState({testlayout});
    }

render() {
            return (<div>
                    <ReactGridLayout>
                        {this.state.testlayout.map((item, i) => {
                                let ChildComponent = item.widget;
                                return 
                                <div onClick={() => this.onClose(item.i)}  data-grid={this.state.testlayout[i]} key={item.i}>
                                    <ChildComponent/>
                                </div>
                            }
                        )}

                    </ReactGridLayout>
                </div>
            );
        }

enter image description here


Solution

  • well, this line of code, removes the last element, as the indexes will not be kept.

    let components= this.state.components.filter((item,k)=>k!=i);
    

    first of, look into the article about Reconcilation. It helps you to understand, why unique, predictable and stable keys are important.