反应:停止映射组件的重新渲染
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反应:停止映射组件的重新渲染相关的知识,希望对你有一定的参考价值。
我有一个无限滚动器,它一次调用一个组件<Goat />
五个,每次给它分配诸如name和image之类的随机属性。往底部滚动并加载另外5个滚动条。当新的5显示为:
shouldComponentUpdate(nextProps){
return false;
}
这很好,但是如果我要将唯一的密钥传递给列表中的每个密钥,它将再次重新呈现页面上所有现有的<Goat />
组件。
传递密钥时是否可以防止这种情况发生?
App.js:
import React from "react";
import Goat from "./components/addGoat";
import "./App.css";
import Toggle from "./components/toggle";
import InfiniteScroll from "react-infinite-scroll-component";
import uuid from "uuid";
import Header from "./components/Header";
import Theme from "./components/Theme";
class App extends React.Component {
state = {
items: Array.from({ length: 5 }),
darkMode: false
};
fetchMoreData = () => {
this.setState({
items: this.state.items.concat(Array.from({ length: 5 }))
});
};
getStyle = () => {
return {
background: this.state.darkMode ? "#464646" : "#eee",
transition: "all 0.4s ease",
color: this.state.darkMode ? "#eee" : "#464646"
};
};
themeToggle = () => {
console.log("changing style");
this.setState({
darkMode: !this.state.darkMode
});
this.getStyle();
};
render() {
return (
<div className="App" style={this.getStyle()}>
<Theme theme={this.themeToggle} />
<Header />
<Toggle>
<InfiniteScroll
dataLength={this.state.items.length}
next={this.fetchMoreData}
hasMore={true}
loader={<h4>Loading...</h4>}
style={this.getStyle()}
>
{this.state.items.map((i, index) => (
<Goat key={uuid.v4()} />
))}
</InfiniteScroll>
</Toggle>
</div>
);
}
}
export default App;
山羊:
import React, { Component } from "react";
class Goat extends Component {
state = {
usedFirstNames: []
};
shouldComponentUpdate(nextProps) {
return false;
}
render() {
const arFirstNames = ["Napoleon", "Albert", "Phil"];
const arLastNames = ["Jones", "Da Goat", "Williams"];
const arStoryStart = [
"Born in hell, this goat is not to be reckoned with.",
"One of 16 siblings, this goat craves attention.",
"This French animal loves baguettes... and anything else edible actually."
];
const arStoryMid = [
"Once tipped off as the next big thing in Winter Sports.",
"The country people believe that this goat can backflip on command.",
"Serial eater of buttered baguettes."
];
const arStoryEnd = [
"This boy has had several medicals and all doctors believe that he will live forever.",
"Has been warned on numerous occasions that he must stop eating double cheese pizzas before his heart gives out."
];
var rand = Math.floor(Math.random() * 100 + 1);
var newFirstName = this.state.usedFirstNames.slice();
let firstName = [];
do {
firstName = arFirstNames[Math.floor(Math.random() * arFirstNames.length)];
this.setState({
usedFirstNames: [...this.state.usedFirstNames, firstName]
});
} while (this.state.usedFirstNames.includes(newFirstName));
// Fix this buy passing props to app js rather than setting state in this component
let lastName = arLastNames[Math.floor(Math.random() * arLastNames.length)];
let randomStory =
arStoryStart[Math.floor(Math.random() * arStoryStart.length)] +
" " +
arStoryMid[Math.floor(Math.random() * arStoryMid.length)] +
" " +
arStoryEnd[Math.floor(Math.random() * arStoryEnd.length)];
//Add check here to see if firstName and/or last name has existing in the previous iterations
//array.includes array.shift array.push
let randomName = firstName + " " + lastName;
return (
<div className="GoatItem" id="Goats" onScroll={this.handleScroll}>
<img
className="GoatImg"
src={"/images/goats/" + rand + ".jpg"}
alt="goat"
/>
<div className="GoatContent">
<p>{randomName}</p>
<div className="GoatStory">
<p>{randomStory}</p>
</div>
</div>
</div>
);
}
}
export default Goat;
当前无键演示-https://lukes-code-infinitescroats.netlify.com
提前感谢。
问题:每次调用uuid
都会生成一个唯一的字符串。因为您是在render函数中调用它的,所以它将强制向所有映射的组件提供新的键。
Docs说:
键可帮助React识别哪些项目已更改,添加或删除。应该为数组内的元素提供键,以赋予元素稳定的身份。
因此,每次父组件中的任何内容发生更改时,都不应给他们一个新的标识。
This Codesandbox准确显示了这一点。您必须在开发工具中启用paint falshing才能检查重新渲染。
解决方案:不要在渲染函数中使用uuid
,而是如果您可以创建对象数组或已经拥有一个对象,则创建一个将保留该孩子ID的键。像这样的[{ ...item, id: uuid() }, ...]
。
当传递唯一的键时,react无法将它们与呈现的原始组件匹配。因此,即使使用shouldComponentUpdate: () => false
,您仍将进行渲染,因为它们是新组件,而不是要更新的组件。
以上是关于反应:停止映射组件的重新渲染的主要内容,如果未能解决你的问题,请参考以下文章