gpt4 book ai didi

javascript - 尽管对所有项目使用唯一键,但在添加新项目时,React 会重新呈现数组中的所有项目

转载 作者:行者123 更新时间:2023-11-29 20:49:45 25 4
gpt4 key购买 nike

原帖

我有一个页面,它使用 Array.prototype.map 呈现包含在 redux 状态中的数组中的每个项目。该数组最初在调用 componentWillMount() 回调时填充,然后在用户请求更多数据时附加,即,当用户滚动到页面底部时,如果有更多项目要获取。我确保在使用 Array.prototype.concat() 附加数组时 redux 状态不会发生变化。然而,当更多的项目被添加到数组中时,尽管为每个项目设置了一个唯一的键,但似乎 react 重新渲染了数组中的每个项目,而不仅仅是新项目。我渲染组件的源代码如下:

this.props.state.list.map((item, index) => {
return (
<Grid className={classes.column} key={item._id} item xs={6} sm={6} md={4}>
<Card className={classes.card}>
<CardActionArea className={classes.cardAction}>
<div className={classes.cardWrapper}>
<div className={classes.outer}>
<div className={classes.bgWrapper}>
<img
className={[classes.bg, "lazyload"].join(" ")}
data-sizes="auto"
data-src={genSrc(item.pictures[0].file)}
data-srcset={genSrcSet(item.pictures[0].file)}
alt={item.name}
/>
</div>
</div>
<CardContent className={classes.cardContent}>
<div className={classes.textWrapper}>
<div className={classes.textContainer}>
<Typography
gutterBottom
className={[classes.text, classes.title].join(" ")}
variant="title"
color="inherit"
>
{item.name}
</Typography>
<Typography
className={[classes.text, classes.price].join(" ")}
variant="subheading"
color="inherit"
>
{item.minPrice === item.maxPrice
? `$${item.minPrice.toString()}`
: `$${item.minPrice
.toString()
.concat(" - $", item.maxPrice.toString())}`}
</Typography>
</div>
</div>
</CardContent>
</div>
</CardActionArea>
</Card>
</Grid>
);
});

这是我的 reducer ,如果你认为它可能与此有关:

import {
FETCH_PRODUCTS_PENDING,
FETCH_PRODUCTS_SUCCESS,
FETCH_PRODUCTS_FAILURE
} from "../actions/products";

let defaultState = {
list: [],
cursor: null,
calls: 0,
status: null,
errors: []
};

const reducer = (state = defaultState, action) => {
switch (action.type) {
case FETCH_PRODUCTS_PENDING:
return {
...state,
status: "PENDING"
};
case FETCH_PRODUCTS_SUCCESS:
return {
...state,
calls: state.calls + 1,
cursor: action.payload.data.cursor ? action.payload.data.cursor : null,
list: action.payload.data.results
? state.list.concat(action.payload.data.results)
: state.list,
status: "READY"
};
case FETCH_PRODUCTS_FAILURE:
return {
...state,
status: "FAIL",
call: state.calls + 1,
errors: [...state.errors, action.payload]
};
default:
return state;
}
};

export default reducer;

我从类似于我的问题的答案中读到,为从数组生成的每个组件设置一个 shouldComponentUpdate() 方法可能会成功,但没有明确的例子说明如何做到这一点。我真的很感激你的帮助。谢谢!

编辑1

我还应该指定,当新项目添加到数组时,从数组呈现的组件完全卸载并重新加载到浏览器 DOM 中。理想情况下,我希望浏览器永远不会卸载现有组件,而只会附加新呈现的组件。

编辑2

这是呈现列表的组件的完整代码。

class Products extends React.Component {

componentDidMount() {
const { fetchNext, fetchStart, filter } = this.props
fetchStart(filter)

window.onscroll = () => {
const { errors, cursor, status } = this.props.state
if (errors.length > 0 || status === 'PENDING' || cursor === null) return
if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
fetchNext(filter, cursor)
}
}
}

render() {
const { classes, title } = this.props

return (
<div className={classes.container}>
<Grid container spacing={0}>
{
this.props.state.status && this.props.state.status === 'READY' && this.props.state.list &&
this.props.state.list.map((item, index) => {
return (
<Grid className={classes.column} key={item._id} item xs={6} sm={6} md={4}>
<Card className={classes.card}>
<CardActionArea className={classes.cardAction}>
<div className={classes.cardWrapper}>
<div className={classes.outer}>
<div className={classes.bgWrapper}>
<img className={[classes.bg, 'lazyload'].join(' ')} data-sizes='auto' data-src={genSrc(item.pictures[0].file)} data-srcset={genSrcSet(item.pictures[0].file)} alt={item.name} />
</div>
</div>
<CardContent className={classes.cardContent}>
<div className={classes.textWrapper}>
<div className={classes.textContainer}>
<Typography gutterBottom className={[classes.text, classes.title].join(' ')} variant="title" color='inherit'>
{item.name}
</Typography>
<Typography className={[classes.text, classes.price].join(' ')} variant='subheading' color='inherit'>
{item.minPrice === item.maxPrice ? `$${item.minPrice.toString()}` : `$${item.minPrice.toString().concat(' - $', item.maxPrice.toString())}`}
</Typography>
</div>
</div>
</CardContent>
</div>
</CardActionArea>
</Card>
</Grid>
)
})
}
</Grid>
</div>
)
}
}

最佳答案

所以事实证明这是一个条件渲染导致渲染列表消失。在我的例子中,我将其设置为只有在所有正在进行的提取操作都已完成时组件才会呈现列表,因此列表当然会在提取调用之间消失。

更改以下内容

    {
this.props.state.status && this.props.state.status === 'READY' && this.props.state.list &&
this.props.state.list.map((item, index) => {
return <Item />
}
}

为此,取消对已完成获取状态的检查解决了我的问题。

    {
this.props.state.list &&
this.props.state.list.map((item, index) => {
return <Item />
}
}

关于javascript - 尽管对所有项目使用唯一键,但在添加新项目时,React 会重新呈现数组中的所有项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52509150/

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