简体   繁体   中英

Does Array.map reuse instance of React component?

I have met weird symptom while I use Array.map to render multiple items in React. In the code below, filtered1 and filtered2 should show same result. However, The result is different.

It seems that Array.map reuse the instance of React component. Is this right behaviour of Array.map?

You can see the full source and demo here .

class Row extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            id: props.data.Id,
            isTrue: props.data.IsTrue
        }
    }
    render () {
        const {data} = this.props
            return (
            <tr>
                <td>{data.Id}</td>
                <td>{data.IsTrue ? 'true' : 'false'}</td>
                <td style={{backgroundColor:(this.state.isTrue ? 'green' : 'red')}}>{this.state.id}</td>
                <td style={{backgroundColor:(this.props.data.IsTrue ? 'green' : 'red')}}>{this.props.data.Id}</td>
            </tr>
        )
    }
}
class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = { filter: 'all' }
    }
    render () {
        const data = [
            {"Id":"1","IsTrue":true},{"Id":"2","IsTrue":true},{"Id":"3","IsTrue":false},{"Id":"4","IsTrue":false},{"Id":"5","IsTrue":true},
            {"Id":"6","IsTrue":true},{"Id":"7","IsTrue":false},{"Id":"8","IsTrue":true},{"Id":"9","IsTrue":true},{"Id":"10","IsTrue":false}]

        const filtered1 = 
            data
            .filter(x => this.state.filter == 'all' || x.IsTrue)
            .map((item, index) => (<Row key={index} data={item} />))

        const filtered2 = 
            data
            .map((item, index) => (<Row key={index} data={item} />))
            .filter(x => this.state.filter == 'all' || x.props.data.IsTrue)

        return (
            <div>
                <select value={this.state.filter} onChange={e => this.setState({filter: e.target.value})}>
                    <option value='all'>All</option>
                    <option value='ts'>Trues</option>
                </select>
                <div>
                  <span>
                    <h1>filter -> map</h1>
                    <table>
                      <thead>
                        <tr>
                          <th>Id</th>
                          <th>IsTrue</th>
                          <th>State Value</th>
                          <th>Props Value</th>
                        </tr>
                      </thead>
                      <tbody>
                        {filtered1}
                      </tbody>
                    </table>                  
                  </span>
                  <span>
                    <h1>map -> filter</h1>
                    <table>
                      <thead>
                        <tr>
                          <th>Id</th>
                          <th>IsTrue</th>
                          <th>State Value</th>
                          <th>Props Value</th>
                        </tr>
                      </thead>
                      <tbody>
                        {filtered2}
                      </tbody>
                    </table>                  
                  </span>
                </div>
            </div>
        )
    }
}

Don't use the index of the array as the key; use some unique information about the item , ex:

key={`${item.Id}:${item.IsTrue}`}

By using the index of the array, React thinks the items are the same even though they are different. React doesn't look inside the item, it only looks at the key value. If the keys are the same, it reuses the "old" component without re-rendering it.

For further reading, here are the docs for Lists and Keys . You'll notice they don't use the index as the key except in one scenario, where they clearly warn that:

Only do this if items have no stable IDs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM