failed to “removeChild” coming in react while dyna

2019-09-01 14:48发布

问题:

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. –

回答1:

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.



回答2:

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.