我試圖通過 nextjs 了解反應的行為。我有一個index.js頁面,其中一個組件Homecard顯示了三次,一個按鈕增加了一個值。
每次我單擊按鈕時,所有Homecard組件都會重新渲染。
index.js
import { Homecard } from '../components/Homecard'
import { useState } from 'react'
export default function Home() {
const [count, increment] = useState(0);
const homecards = [
{
"main": "main0",
"sub": "sub0",
"desc": "Desc0",
"nav": [{
"href": "/page0",
"value": "see"
}]
},
{
"main": "main1",
"sub": "sub1",
"desc": "Desc1",
"nav": [{
"href": "/page1",
"value": "see"
}]
},
{
"main": "main2",
"sub": "sub2",
"desc": "Desc2",
"nav": [{
"href": "/page2",
"value": "see"
}]
}
];
const handleCount = () => {
increment(count => count 1);
}
return (
<>
<div className='d-flex justify-content-between' style={{ marginLeft: '-1.5rem' }}>
{
homecards.map((homecard, index) => (
<Homecard
key={index}
main={homecard.main}
sub={homecard.sub}
desc={homecard.desc}
nav={homecard.nav}
/>
))
}
</div>
<button onClick={handleCount}>increment {count}</button>
</>
)
}
homecard.js
export default function Homecard({ main, sub, desc, nav }) {
console.log('render Homecard');
return (
<div className={`${styles.homecard}`}>
<div>
<h3>
{main}
{sub &&
<span>{sub}</span>
}
</h3>
<p>{desc}</p>
{nav &&
<ul>
{nav.map((link, index) => (
<li key={index}>
<Link href={link.href}>
<a>{link.value}</a>
</Link>
</li>
))}
</ul>
}
</div>
</div>
)
}
我試著Homecard像這樣用 React.memo包裝我的
const Homecard = React.memo(({ main, sub, desc, nav }) => {})
console.log('render Homecard');但是當我的按鈕被點擊時,我仍然可以看到。我怎樣才能只更新我的按鈕而不更新其他組件?
uj5u.com熱心網友回復:
問題是您在每次渲染時都在重新創建陣列,因此每個物件都是一個新物件,因此會看到道具的差異并且不會優化后續的重新渲染。homecardsHomenavReact.memo
有幾種方法可以修復它:
定義
homecards外部Home;它是不變的,因此沒有理由在每次Home呼叫時都重新創建它。如果由于某種原因你不能這樣做,你可以將第二個引數傳遞給
React.memo"areEqual" 函式,它將接收舊道具和新道具;在函式中,進行深度比較以查看nav物件是否具有相同的屬性值,即使它們是不同的物件。
#1 的示例:
顯示代碼片段
const { useState } = React;
/*export default*/ const Homecard = React.memo(({ img, main, sub, desc, nav }) => {
console.log('render Homecard');
return (
<div className={`${""/*styles.homecard*/}`}>
<div>
<h3>
{main}
{sub &&
<span>{sub}</span>
}
</h3>
<p>{desc}</p>
{nav &&
<ul>
{nav.map((link, index) => (
<li key={index}>
<a href={link.href}>
{link.value}
</a>
</li>
))}
</ul>
}
</div>
</div>
)
});
const homecards = [
{
"main": "main0",
"sub": "sub0",
"desc": "Desc0",
"nav": [{
"href": "/page0",
"value": "see"
}]
},
{
"main": "main1",
"sub": "sub1",
"desc": "Desc1",
"nav": [{
"href": "/page1",
"value": "see"
}]
},
{
"main": "main2",
"sub": "sub2",
"desc": "Desc2",
"nav": [{
"href": "/page2",
"value": "see"
}]
}
];
/*export default*/ function Home() {
const [count, increment] = useState(0);
const handleCount = () => {
increment(count => count 1);
}
return (
// Sadly, Stack Snippets don't support <>...</>
<React.Fragment>
<div className='d-flex justify-content-between' style={{ marginLeft: '-1.5rem' }}>
{
homecards.map((homecard, index) => (
<Homecard
key={index}
main={homecard.main}
sub={homecard.sub}
desc={homecard.desc}
nav={homecard.nav}
/>
))
}
</div>
<button onClick={handleCount}>increment {count}</button>
</React.Fragment>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Home />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
(警告:為了在 Stack Snippets 中進行這項作業,我進行了一些小改動,例如替換Link和使用React.Fragment而不是<>...</>,因此不要將其直接復制并粘貼回您的專案中,只需移入homecards現有代碼即可。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/479166.html
標籤:javascript 反应 下一个.js
