组件重新渲染时状态不更新?
Posted
技术标签:
【中文标题】组件重新渲染时状态不更新?【英文标题】:state is not updating when the component re renders? 【发布时间】:2021-02-26 12:11:17 【问题描述】:我正在制作一个 Nextjs 抽认卡应用。我正在传递这样的甲板结构:
const deck =
title: 'React 101',
flashcards: [flashcardOne, flashcardTwo],
;
作为Deck
组件的道具。该组件显示抽认卡中的第一张卡片和一个“下一步”按钮以增加索引并显示抽认卡中的下一张卡片。
Card
组件非常简单,根据状态front
显示卡片的正面和背面。
这是我到目前为止得到的,它正在工作,但如果我在卡片显示答案 (flashcard.back
) 时单击“下一步”,下一张卡片将与答案一起出现。而且我不确定为什么,当我单击“下一步”时,Card
组件不是重新呈现吗?如果组件重新渲染,front
会被设置为 true 吗?
export default function Deck( deck )
const [cardIndex, setCardIndex] = useState(0);
const title, flashcards = deck;
return (
<div className=styles.container>
<main className=styles.main>
<h1 className=styles.title>title</h1>
cardIndex < flashcards.length ? (
<>
<div className=styles.grid>
<Card flashcard=flashcards[cardIndex] />
</div>
<button onClick=() => setCardIndex((cardIndex) => cardIndex + 1)>
Next
</button>
</>
) : (
<>
<div>End</div>
<button>
<Link href='/'>
<a>Go to Home</a>
</Link>
</button>
<button onClick=() => setCardIndex(0)>Play again</button>
</>
)
</main>
</div>
);
export function Card( flashcard )
const [front, setFront] = useState(true);
return (
<>
front ? (
<div
className=`$globalStyles.card $styles.card`
onClick=() => setFront(false)
>
<p className=styles.front>flashcard.front</p>
</div>
) : (
<div
className=`$globalStyles.card $styles.card`
onClick=() => setFront(true)
>
<p className=styles.back>flashcard.back</p>
</div>
)
</>
);
【问题讨论】:
【参考方案1】:当状态改变时,卡片会重新渲染,但不会重新挂载。因此,现有状态不会被重置。
当抽认卡道具发生变化时调用setFront(true)
:
const [front, setFront] = useState(true);
useLayoutEffect(() =>
setFront(true);
, [flashcard]);
我使用useLayoutEffect
而不是useEffect
来确保尽快设置front
,而不是在绘制周期之后(这可能会导致闪烁)。
您还可以显着瘦身 Card
JSX:
export function Card( flashcard )
const [front, setFront] = useState(true);
const face = front ? 'front' : 'back';
return (
<div
className=`$globalStyles.card $styles.card`
onClick=() => setFront(!front)
>
<p className=styles[face]>flashcard[face]</p>
</div>
);
【讨论】:
天啊!我只是想找到我的代码参考!哈哈。谢谢,现在我对useLayoutEffect
有所了解!
globalStyles.card + " " + styles.card
小于 `$globalStyles.card $styles.card`
对吧?
两者都可以正常工作,无论哪种方式,语法对我来说都不错。一种可以连接,也可以使用模板文字。
感谢您的回答。一个问题,应该是onClick= () => setFront((prevOpen) => !prevOpen)
?
@saralance 这也可以,但没必要。因为此时外部的front
变量是可见的,所以您可以使用setFront(!front)
,对吧?【参考方案2】:
好的,我想我也遇到了同样的问题。由于您正在使用功能组件,并且您正在重新使用相同的组件,或者更确切地说,您并没有真正卸载和重新安装组件,您只是在更改道具,这种情况发生了。为此,您需要先执行useEffect()
,然后执行setFront(true)
。
这是我在应用中使用的代码。
useEffect(() =>
setFront(true);
, [flashcard]);
这是我在Word.js
文件中使用的内容。
【讨论】:
以上是关于组件重新渲染时状态不更新?的主要内容,如果未能解决你的问题,请参考以下文章