在 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] 中的值发生变化时。