Ответ 1
Вы используете PureComponent, которые делают неглубокое сравнение, тогда ваш компонент MyRow
не должен быть перезагружен при добавлении каждого нового элемента (пожалуйста, следуйте приведенному ниже примеру кода).
Есть ли способ добавить только добавленный элемент в список, а не повторно отобразить весь список?
Согласно вашему вопросу - Да, использование PureComponent
должно отображать только один раз новый элемент:
Вот что говорит React docs:
Если ваша функция React components render() отображает тот же результат при одинаковых реквизитах и состоянии, вы можете использовать React.PureComponent для повышения производительности в некоторых случаях.
Пример кода PureComponent
:
Вы можете проверить образец кода, который я сделал для вас.
Вы увидите, что компонент Item
всегда отображается только 1 раз, потому что мы используем React.PureComponent
. Чтобы доказать мое утверждение, каждый раз, когда Item
отображается, я добавил текущее время рендеринга. В примере вы увидите, что Item
Rendered at:
time всегда один и тот же, потому что он отображается только 1 раз.
const itemsReducer = (state = [], action) => {
if (action.type === 'ADD_ITEM') return [ ...state, action.payload]
return state
}
const addItem = item => ({
type: 'ADD_ITEM',
payload: item
})
class Item extends React.PureComponent {
render () {
// As you can see here, the 'Item' is always rendered only 1 time,
// because we use 'React.PureComponent'.
// You can check that the 'Item' 'Rendered at:' time is always the same.
// If we do it with 'React.Component',
// then the 'Item' will be rerendered on each List update.
return <div>{ this.props.name }, Rendered at: { Date.now() }</div>
}
}
class List extends React.Component {
constructor (props) {
super(props)
this.state = { intervalId: null }
this.addItem = this.addItem.bind(this)
}
componentDidMount () {
// Add new item on each 1 second,
// and keep its 'id', in order to clear the interval later
const intervalId = setInterval(this.addItem, 1000)
this.setState({ intervalId })
}
componentWillUnmount () {
// Use intervalId from the state to clear the interval
clearInterval(this.state.intervalId)
}
addItem () {
const id = Date.now()
this.props.addItem({ id, name: 'Item - ${id}' })
}
renderItems () {
return this.props.items.map(item => <Item key={item.id} {...item} />)
}
render () {
return <div>{this.renderItems()}</div>
}
}
const mapDispatchToProps = { addItem }
const mapStateToProps = state => ({ items: state })
const ListContainer = ReactRedux.connect(mapStateToProps, mapDispatchToProps)(List)
const Store = Redux.createStore(itemsReducer)
const Provider = ReactRedux.Provider
ReactDOM.render(
<Provider store={Store}>
<ListContainer />
</Provider>,
document.getElementById('container')
)
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.0/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.7/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.min.js"></script>
<div id="container">
<!-- This element contents will be replaced with your component. -->
</div>