gpt4 book ai didi

javascript - React/Redux 渲染一个每秒更新的列表

转载 作者:可可西里 更新时间:2023-11-01 01:18:33 24 4
gpt4 key购买 nike

我有一个 react 组件,每秒从 redux 存储接收 Prop 。新状态的数组与上一个数组不同。具体来说,每一秒都有一个元素被添加到数组中。例如:在一种状态下,数组是:

[1, 2, 3, 4, 5, 6]

下一个状态

[1, 2, 3, 4, 5, 6, 7]

我的 reducer :

return {
...state,
myList: [ payload, ...state.myList.filter(item => payload.id !== item.id).slice(0, -1) ]
}

现在,在我的 React 组件中,我订阅了这个状态,并且对于每次更改,列表都会重新呈现。

import React, { Component } from 'react';
import MyRow from './MyRow';

class MyList extends Component {

render() {

return (

<div>

{this.props.myList.map((list, index) => (
<MyRow key={list.id} data={list}/>
))}

</div>

);
}
}

function select({ myList }) {
return { myList };
}

export default connect(select)(MyList);

在 MyRow.js 中

import { PureComponent } from 'react';

class MyRow extends PureComponent {

render() {

const data = this.props.data;

return (
<div>
{data.id} - {data.name}
</div>
);

}
}
export default MyRow;

现在,我的问题是:重新渲染已经渲染过的每个元素对我来说成本很高。 MyRow 大量使用样式组件和其他昂贵的操作。这导致 React 在状态更新时每秒重新渲染整个列表。如果更新不到 1 秒,比如每秒 4 次更新,情况会变得更糟。在这种情况下,React 应用程序会崩溃。

有没有办法只将新添加的项目添加到列表中而不重新渲染整个列表?

谢谢

最佳答案

您正在使用 PureComponent ,做浅比较,然后你的组件 MyRow应该在添加的每个新项目上重新呈现(请按照我下面的代码示例)。

Is there any way to only add the newly added item to the list and not re-render the whole list?

根据您的问题 - 是的,使用 PureComponent应该只渲染 1 次新项目:

这是 React's docs 的内容说:

If your React component’s render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.

PureComponent的代码示例:

您可以查看我为您制作的代码示例。

您会看到 Item组件总是只渲染 1 次,因为我们使用 React.PureComponent .为了证明我的说法,每次Item渲染后,我添加了当前渲染时间。从示例中您将看到 Item Rendered at:时间总是相同的, 因为它只渲染了 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/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/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's contents will be replaced with your component. -->
</div>

解决方案:

  1. 如果性能问题是由 MyRow 引起的重新渲染,请找出重新渲染的原因,因为它不应该发生,因为PureComponent用法。
    • 您可以尝试简化您的reducer,以便检查/调试是不是reducer 导致了问题。例如,只需将新项目添加到列表中(不执行任何其他过滤、切片等操作):myList: [ ...state.myList, payload ]
    • 请确保您始终通过相同的 key 到您的项目组件 <MyRow key={list.id} data={list} /> .如果keydata Prop 被改变,那么组件将被重新渲染。

  1. 这里有一些其他的库,它们代表列表的高效呈现。我相信他们会给我们一些替代方案或见解:

    • react-virtualized - 用于高效呈现大型列表和表格数据的 React 组件
    • react-infinite - 基于 UITableView 的浏览器就绪高效滚动容器

关于javascript - React/Redux 渲染一个每秒更新的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50430459/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com