在 React Redux 中使用状态更改触发模态
Using state change to trigger modal in React Redux
我正在 React Redux 中构建一个游戏,我有一个条件,在发牌时,如果牌数超过一定数量,我想要一个模式,以便用户可以 select 一个要丢弃。
我通过将名为“cardHandOverflow”的状态的一部分切换为 true 在游戏逻辑中执行此操作,并且我希望模式在此条件下呈现。我为此使用 React Modal 库。
但是我得到了错误
react-dom.development.js:14997 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
这是我使用的代码:
export const CardHand: React.FC = () => {
const cardHandOverflow = useSelector((state: RootState) => state.gameStateReducer.players.filter(player => player.id === Player.id)[0].cardHandOverflow);
const [modalIsOpen, setIsOpen] = useState(false);
const closeModal = () => {
setIsOpen(false)
}
if (cardHandOverflow) {
setIsOpen(true)
}
return (
<>
{modalIsOpen ?
<DiscardModal
modalIsOpen={modalIsOpen}
closeModal={closeModal}
discardableCards={cards}
/> : null}
</>
)
它显然通过 useSelector 和状态更改重新触发创建了某种渲染循环,但是当我将其切换为按钮时,模态渲染正常。我怎样才能让状态改变来渲染模态一次(所以它的行为就像一个点击事件)?
非常感谢:-)
这是由于 setIsOpen(true);
当 cardHandOverflow
为真时造成的。
setIsOpen
会导致重新渲染,即使值没有改变,并且由于它直接是您的功能组件逻辑的一部分,所以它将 运行 永远渲染,而 cardHandOverflow
是是的。
为了避免这些循环,你应该使用 React 提供的钩子,在这种情况下 useEffect
是最合适的。
export const CardHand: React.FC = () => {
const cardHandOverflow = useSelector((state: RootState) => state.gameStateReducer.players.filter(player => player.id === Player.id)[0].cardHandOverflow);
const [modalIsOpen, setIsOpen] = useState(false);
const closeModal = () => {
setIsOpen(false)
}
useEffect(() => {
if (cardHandOverflow) {
setIsOpen(true)
}
}, [cardHandOverflow, setIsOpen])
return (
<>
{modalIsOpen ?
<DiscardModal
modalIsOpen={modalIsOpen}
closeModal={closeModal}
discardableCards={cards}
/> : null}
</>
)
}
useEffect
只会 运行 组件挂载时包含的代码以及依赖项数组 [cardHandOverflow, setIsOpen]
中的值发生变化时。
我正在 React Redux 中构建一个游戏,我有一个条件,在发牌时,如果牌数超过一定数量,我想要一个模式,以便用户可以 select 一个要丢弃。
我通过将名为“cardHandOverflow”的状态的一部分切换为 true 在游戏逻辑中执行此操作,并且我希望模式在此条件下呈现。我为此使用 React Modal 库。
但是我得到了错误
react-dom.development.js:14997 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
这是我使用的代码:
export const CardHand: React.FC = () => {
const cardHandOverflow = useSelector((state: RootState) => state.gameStateReducer.players.filter(player => player.id === Player.id)[0].cardHandOverflow);
const [modalIsOpen, setIsOpen] = useState(false);
const closeModal = () => {
setIsOpen(false)
}
if (cardHandOverflow) {
setIsOpen(true)
}
return (
<>
{modalIsOpen ?
<DiscardModal
modalIsOpen={modalIsOpen}
closeModal={closeModal}
discardableCards={cards}
/> : null}
</>
)
它显然通过 useSelector 和状态更改重新触发创建了某种渲染循环,但是当我将其切换为按钮时,模态渲染正常。我怎样才能让状态改变来渲染模态一次(所以它的行为就像一个点击事件)?
非常感谢:-)
这是由于 setIsOpen(true);
当 cardHandOverflow
为真时造成的。
setIsOpen
会导致重新渲染,即使值没有改变,并且由于它直接是您的功能组件逻辑的一部分,所以它将 运行 永远渲染,而 cardHandOverflow
是是的。
为了避免这些循环,你应该使用 React 提供的钩子,在这种情况下 useEffect
是最合适的。
export const CardHand: React.FC = () => {
const cardHandOverflow = useSelector((state: RootState) => state.gameStateReducer.players.filter(player => player.id === Player.id)[0].cardHandOverflow);
const [modalIsOpen, setIsOpen] = useState(false);
const closeModal = () => {
setIsOpen(false)
}
useEffect(() => {
if (cardHandOverflow) {
setIsOpen(true)
}
}, [cardHandOverflow, setIsOpen])
return (
<>
{modalIsOpen ?
<DiscardModal
modalIsOpen={modalIsOpen}
closeModal={closeModal}
discardableCards={cards}
/> : null}
</>
)
}
useEffect
只会 运行 组件挂载时包含的代码以及依赖项数组 [cardHandOverflow, setIsOpen]
中的值发生变化时。