React 状态在重新渲染后重置

Posted

技术标签:

【中文标题】React 状态在重新渲染后重置【英文标题】:React state gets resetted after rerendering 【发布时间】:2021-06-11 15:28:47 【问题描述】:

我是 React 新手,面临更新功能组件状态的问题。

我有一个组件TinderCards.js,如下所示,它基本上从上下文提供程序中获取对象列表,并为每个对象创建一个TinderCard (https://www.npmjs.com/package/react-tinder-card),它应该在何时更新count刷卡(onSwipe)。

但是,每次刷卡时,count 会增加到 1,然后不再继续。

例如

初始计数值:0

刷第一张卡 => count = 1

刷第二张卡 => count = 1(应该是2)

刷第三张卡 => count = 1(应该是 3)

我尝试将 count 值作为组件状态的一部分和称为 ResultsContext.js 的全局上下文的一部分,但两者都会导致相同的行为。

注意test-btn 类的按钮在 onClick 处的行为完全符合我的要求。但是,TinderCard 组件的 onSwipe 却没有,尽管它基本上是相同的代码,这让我抓狂。

TinderCards.js

import React,  useState, useEffect, useContext  from "react";
import TinderCard from "react-tinder-card";
import StocksContext from "./StocksContext";
import ResultsContext from "./ResultsContext";
import "./Tindercards.css";

function TinderCards(props) 
  // const [count, setCount] = useState(0);
  const  count, setCount  = useContext(ResultsContext);
  const  stocks, setStocks  = useContext(StocksContext);

  return (
    <div>
      <div className="tinderCards__cardContainer">
        <div>
          Count: count
          <button className="test-btn" onClick=() => setCount(count + 1)>Increment</button>
        </div>
        <div className="main__container">
          stocks.map((stock) => (
            <TinderCard
              onSwipe=() => setCount(count + 1)
              className="swipe"
              key=stock.name
              preventSwipe=["up", "down"]
            >
              <div className="card">
                <div style= height: "100%" >
                  <img
                    src=stock.url
                    style=
                      objectFit: "contain",
                      height: "100%",
                      width: "100%",
                      backgroundColor: "white",
                    
                  />
                </div>
              </div>
              <h3 style= backgroundColor: "white" >$stock.name</h3>
            </TinderCard>
          ))
        </div>
      </div>
    </div>
  );


export default TinderCards;

感谢您的帮助!非常感谢!

【问题讨论】:

嗨,请阅读github.com/3DJakob/react-tinder-card/issues/21。似乎与您上面的问题有关 【参考方案1】:

onSwipe 处理程序中的每个 count 变量:

() => setCount(count + 1)

是一个闭包,在它们被渲染时包含 count 的值 - 即 0。其中一个正在运行的函数实际上并没有改变 count 变量的值 - 它只是触发重新渲染父组件。那些其他孩子仍然保留他们的 onSwipe 处理程序,它只是将计数设置为 2(比渲染它们时 count 的值多 1) - 这就是您所看到的。

这里的简单解决方案是将update function 传递给setCount,而不是硬编码值:

onSwipe=() => setCount(prevCount => prevCount + 1)

这将确保始终读取count 状态的“最新值”,并以 1 递增。

【讨论】:

出于好奇,为什么test-btn 无需这样做就能完美运行?欣赏! 好问题 - 我真的不确定,假设您的意思是“完美工作”,即使您也刷了一些“TinderCards”,它总是将计数增加 1。我希望那里有同样的问题。 (当我写答案时,我没有在你的代码中发现这一点。) 是的,这就是我的意思——我每刷一张卡,它就会增加 1。非常感谢您的帮助,非常感谢!

以上是关于React 状态在重新渲染后重置的主要内容,如果未能解决你的问题,请参考以下文章

Redux dispatch 导致组件本地状态重置

防止多步 Formik 表单在重新渲染上一步时重置表单控件输入

React 子组件在父组件中更新状态后如何将其重置回原始状态

React 组件表在更新状态后被多次渲染或复制

ReactJs 保留多个react 值,刷新后不重置状态

如何在 useEffect 中使用 setTimeout 重置 React 钩子状态