Javascript 为什么';当其道具更改时,此React组件是否重新渲染?
我已经创建了一个重新渲染问题的简化版本,我正在处理一个应用程序 实际上,Javascript 为什么';当其道具更改时,此React组件是否重新渲染?,javascript,reactjs,react-native,react-hooks,Javascript,Reactjs,React Native,React Hooks,我已经创建了一个重新渲染问题的简化版本,我正在处理一个应用程序 实际上,displayement1和displayement2是两个复杂的组件 displayement2这里是通过一个简单的数字数组(通过其道具numbers提供)迭代并显示它们 问题:当数字道具后面的数组在主组件应用程序中更新时(在这种情况下,通过单击向数组添加数字按钮,我希望DisplayElement2使用更新的数组重新渲染,但它没有,为什么不呢 如果单击“显示1”,然后在“显示2”上单击“上一步”,则更新后的阵列将渲染
displayement1
和displayement2
是两个复杂的组件
displayement2
这里是通过一个简单的数字数组(通过其道具numbers
提供)迭代并显示它们
问题:当数字
道具后面的数组在主组件应用程序
中更新时(在这种情况下,通过单击向数组添加数字按钮,我希望DisplayElement2
使用更新的数组重新渲染,但它没有,为什么不呢
如果单击“显示1”,然后在“显示2”上单击“上一步”,则更新后的阵列将渲染
App.js
从“React”导入React;
从“@material ui/core”导入{Paper}”;
导出默认函数DisplayComponent2(道具){
返回(
这是DisplayComponent2
{props.number.map((currNumber,currIndex)=>{
返回{currNumber};
})}
);
}
对于你的App.js,可以考虑这样做,其中显示状态是枚举的,我们已经删除了useMoom
import React, { useState } from "react";
import "./styles.css";
import DisplayComponent1 from "./DisplayComponent1";
import DisplayComponent2 from "./DisplayComponent2";
import { Button } from "@material-ui/core";
const DisplayStatEnum = {COMPONENT1: 0, COMPONENT2: 1};
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
////////////////////////////////////////////////
const component1 = <DisplayComponent1 />;
const component2 = <DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>;
////////////////////////////////////////////////
const [currentDisplayComponent, setCurrentDisplayComponent]
= useState(DisplayStatEnum.COMPONENT2);
const componentSelected =
currentDisplayComponent === DisplayStatEnum.COMPONENT1
? component1
: component2;
return (
<div className="App">
<div>
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent(DisplayStatEnum.COMPONENT1)}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent(DisplayStatEnum.COMPONENT2)}
>
Show Display 2
</Button>
</div>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{componentSelected}
</div>
);
}
import React,{useState}来自“React”;
导入“/styles.css”;
从“/DisplayComponent1”导入DisplayComponent1;
从“/DisplayComponent2”导入DisplayComponent2;
从“@material ui/core”导入{Button}”;
const DisplayStatEnum={COMPONENT1:0,COMPONENT2:1};
导出默认函数App(){
const[numbersToDisplay,setNumbersToDisplay]=useState([1,2,3]);
////////////////////////////////////////////////
常量分量1=;
常量分量2=;
////////////////////////////////////////////////
常量[currentDisplayComponent,setCurrentDisplayComponent]
=使用状态(DisplayStatEnum.COMPONENT2);
所选常量组件=
currentDisplayComponent==DisplayStatEnum.COMPONENT1
?组件1
:组件2;
返回(
setCurrentDisplayComponent(DisplayStatEnum.COMPONENT1)}
>
显示1
setCurrentDisplayComponent(DisplayStatEnum.COMPONENT2)}
>
显示2
{
让tempArray=Array.from(numbersToDisplay);
temparay.push(4);
setNumbersToDisplay(tempArray);
}}
>
将数字添加到数组中
{componentSelected}
);
}
您的组件没有使用更新的道具重新渲染的原因是,您的组件的前一个实例存储在您用来渲染的currentDisplayComponent
状态中
- 使用当前代码的一个棘手的解决方法是使用useEffect并更新激活的组件实例
- 但是,在这种情况下,最好的解决方案是将
移出状态,并基于选定的组件字符串状态呈现这些实例组件实例
React.memo
export default React.memo(function DisplayComponent2(props) {
return (
<Paper>
<p>This is DisplayComponent2</p>
{props.numbers.map((currNumber, index) => {
return <div key={index}>{currNumber}</div>;
})}
</Paper>
);
});
export default React.memo(功能显示组件2(道具){
返回(
这是DisplayComponent2
{props.number.map((currNumber,index)=>{
返回{currNumber};
})}
);
});
App.js
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
const [currentDisplayComponent, setCurrentDisplayComponent] = useState(
"component1"
);
const getCurrentComponent = currentDisplayComponent => {
switch (currentDisplayComponent) {
case "component1":
return <DisplayComponent1 />;
case "component2":
return (
<DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>
);
default:
return null;
}
};
return (
<div className="App">
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent("component1")}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent("component2")}
>
Show Display 2
</Button>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{getCurrentComponent(currentDisplayComponent)}
</div>
);
}
导出默认函数App(){
const[numbersToDisplay,setNumbersToDisplay]=useState([1,2,3]);
常量[currentDisplayComponent,setCurrentDisplayComponent]=useState(
“组件1”
);
常量getCurrentComponent=currentDisplayComponent=>{
开关(currentDisplayComponent){
案例“组件1”:
返回;
案例“组件2”:
返回(
);
违约:
返回null;
}
};
返回(
setCurrentDisplayComponent(“component1”)}
>
显示1
setCurrentDisplayComponent(“component2”)}
>
显示2
{
让tempArray=Array.from(numbersToDisplay);
temparay.push(4);
setNumbersToDisplay(tempArray);
}}
>
将数字添加到数组中
{getCurrentComponent(currentDisplayComponent)}
);
}
可能是因为您已将组件进行了记忆。有一点提示,不要将组件放在组件内部,否则React diff将失败,因为每个渲染都将有一个新的组件类。您可能已使用
useMemo
来防止这种情况发生,但这似乎非常棘手。在这种情况下,您建议的“最佳实践”方法是什么一个场景?就像一场梦。非常感谢。很高兴能帮助西蒙:-)
import React, { useState } from "react";
import "./styles.css";
import DisplayComponent1 from "./DisplayComponent1";
import DisplayComponent2 from "./DisplayComponent2";
import { Button } from "@material-ui/core";
const DisplayStatEnum = {COMPONENT1: 0, COMPONENT2: 1};
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
////////////////////////////////////////////////
const component1 = <DisplayComponent1 />;
const component2 = <DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>;
////////////////////////////////////////////////
const [currentDisplayComponent, setCurrentDisplayComponent]
= useState(DisplayStatEnum.COMPONENT2);
const componentSelected =
currentDisplayComponent === DisplayStatEnum.COMPONENT1
? component1
: component2;
return (
<div className="App">
<div>
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent(DisplayStatEnum.COMPONENT1)}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent(DisplayStatEnum.COMPONENT2)}
>
Show Display 2
</Button>
</div>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{componentSelected}
</div>
);
}
export default React.memo(function DisplayComponent2(props) {
return (
<Paper>
<p>This is DisplayComponent2</p>
{props.numbers.map((currNumber, index) => {
return <div key={index}>{currNumber}</div>;
})}
</Paper>
);
});
export default function App() {
const [numbersToDisplay, setNumbersToDisplay] = useState([1, 2, 3]);
const [currentDisplayComponent, setCurrentDisplayComponent] = useState(
"component1"
);
const getCurrentComponent = currentDisplayComponent => {
switch (currentDisplayComponent) {
case "component1":
return <DisplayComponent1 />;
case "component2":
return (
<DisplayComponent2
style={{ background: "red" }}
numbers={numbersToDisplay}
/>
);
default:
return null;
}
};
return (
<div className="App">
<Button
variant="contained"
color="secondary"
onClick={() => setCurrentDisplayComponent("component1")}
>
Show Display 1
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setCurrentDisplayComponent("component2")}
>
Show Display 2
</Button>
<Button
variant="contained"
style={{ marginLeft: 50 }}
onClick={() => {
let tempArray = Array.from(numbersToDisplay);
tempArray.push(4);
setNumbersToDisplay(tempArray);
}}
>
Add number to array
</Button>
{getCurrentComponent(currentDisplayComponent)}
</div>
);
}