EdG
EdG

Reputation: 2351

failed to "removeChild" coming in react while dynamically updating an array

I am having an array "personArray" in the state of my react component. I have a search bar in the component. Based on what I type in search bar, I make a request to an api and update the state of "personArray". I mapping this "personArray" in my render method. (see code below)

Problem: When I type the first letter in the search bar, the list of people gets updated and reflects in render properly. When as soon as I type the second letter, I get this error saying

Uncaught DOMException: Failed to execute 'removeChild' on 'Node':
 The node to be removed is not a child of this node.

Code:

THis is my search bar

<input type="text" className="input-hidden" placeholder="search" ref="personSearch" id="personSearch" onChange={()=>{this.searchForPerson()}}>

This is the searchForPerson function (here I search and update my state)

searchForPerson(){

    var that = this

    let req = fetch(url,
        {
            method: "GET",
            headers: {
                "Authorization": "Token " + this.props.token_reducer.token,
                "content-type": "application/json"
            }
        })
    req.then(response => response.json()
    ).then(response => {
        console.log("type it")
        console.log(response)
        that.setState({ personArray: response.results }, () => {
            //new SimpleBar(document.getElementById('items-listing'))
            console.log(this.state.personArray)
        })
    })
}

This is my where I map "personArray"

<div className="items-listing" id="items-listing">
    {this.state.personArray && this.state.personArray.map((item, i) => { return
    <div className={`item ${this.state.activePersonRow===i
        ? "active" : ""}`} key={i} onClick={()=> { this.onPersonRowClick(i, item.name, item.id) }}>
        <div className="item-img" style={{backgroundImage:`url(${item.personframes.length !==0 ? item.personframes[0].file : ""})`}}></div>
        <div className="item-title">{item.name}
            <br/>
            <div className="item-sub">{item.occupation}</div>
        </div>
        <div className="item-count">{item.personframes.length}</div>
    </div>
    })}
</div>

UPDATE: I observed something. When the api returns equal to or more than 10 items array then it works. As soon as api return an array with less than 10 items then the error comes. No idea why but this is the case. –

Upvotes: 0

Views: 340

Answers (2)

EdG
EdG

Reputation: 2351

The only solution which worked for me was to wrap the map content in a table. Put each element of map inside a "tr" and render map in a table.

Something like this:

 <table className="item-table">
{this.state.personArray && this.state.personArray.map((item, i) => {
    return <tr  id={item.id}>
        <div className={`item ${this.state.activePersonRow === i ? "active" : ""}`}
             onClick={() => {
                 this.onPersonRowClick(i, item.name, item.id)
             }}>
            <div className="item-img" style={{backgroundImage:`url(${item.personframes.length !==0 ? item.personframes[0].file : ""})`}}></div>
            <div className="item-title">{item.name}<br/>
                <div className="item-sub">{item.occupation}</div>
            </div>
            <div className="item-count">{item.personframes.length}</div>
        </div>
    </tr>
})}
</table>

For some reason the was giving error. Put it in a table solved the issue. If someone has the reason for why such behaviour was occurring then please suggest.

Upvotes: 0

AlexeyOm
AlexeyOm

Reputation: 11

Using array index as key in .map is considered an antipattern, it is in the docs https://reactjs.org/docs/lists-and-keys.html. Reacts uses keys to understand what node is what and when order and amount of nodes change and indexes remain the same React might have hard time figuring out what is what. Try using some data that is unique for your persons. Maybe you have ID's in your database, that will do just fine.

Upvotes: 1

Related Questions