Исходное сообщение
У меня есть страница, которая отображает каждый элемент в массиве, содержащемся в состоянии избыточности, используя Array.prototype.map.Массив первоначально заполняется при вызове обратного вызова componentWillMount (), а затем добавляется, когда пользователь запрашивает больше данных, т. Е. Когда пользователь прокручивает страницу до конца и если есть еще элементы для выборки.Я удостоверяюсь, что состояние приращения не изменено, когда массив присоединен, используя Array.prototype.concat ().Тем не менее, когда в массив добавляется больше элементов, создается впечатление, что реагирует на рендеринг каждый элемент массива, а не только новые элементы, несмотря на установку уникального ключа для каждого элемента.Мой исходный код для рендеринга компонентов выглядит следующим образом:
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>
);
});
Вот мой редуктор, если вы думаете, что это может иметь какое-то отношение к этому:
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 браузера при добавлении новых элементов в массив.В идеале я бы хотел, чтобы браузер никогда не отключал существующие компоненты и только добавлял только что созданные компоненты.
Edit 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>
)
}
}