提问者:小点点

反应功能组件的使用状态


用户可以对n项进行投票。有两种React状态:

>

  • vote 是用户对每个项目的投票数组。

    const [votes, setVotes] = useState({});

    voteChange指示用户更改对任何项目的投票次数。

    const[voteChanges,setVoteChanges]=useState(0);

    我们在useEffect中定义了一个数据库侦听器。当在数据库中添加/更改投票时,将调用侦听器。我们需要状态<code>投票</code>将每个新的投票与<code>中的前一个值进行比较,以决定是否增加<code>voteChanges</code>。然而,我们不能在useEffect中将投票定义为依赖项,否则我们将陷入无限循环。要访问投票的当前值,我们使用其函数更新。在setVotes的功能更新中调用setVoteChanges可以吗?如果没有,为什么,你会如何解决这个问题?

      useEffect(() => {
        databaseListener((changes) => {
          setVotes((oldVotes) => {
            const oVotes = { ...oldVotes };
            for (let change of changes) {
              const itemId = change.id;
              const newVote = change.vote;
              if (oVotes[itemId] !== newVote) {
                setVoteChanges(oldCount => oldCount + 1);
              }
              oVotes[itemId] = newVote;
            }
            return oVotes;
          });
        });
      });
    

    这是代码 https://codesandbox.io/s/react-tracking-vote-changes-x3jhwj?file=/src/App.js


  • 共1个答案

    匿名用户

    因此,首先,您需要确保此处的useEffect只运行一次,因为您不需要每次都注册到databaseListener。其次,您需要记住状态更改将导致重新渲染的事实,因此最好在变量中计算voteChange,然后应用一次。检查下面的代码段。

    useEffect(() => {
    
        databaseListener((changes) => {
    
          let voteChanges = 0;
    
          setVotes((oldVotes) => {
            const oVotes = { ...oldVotes };
            for (let change of changes) {
              const itemId = change.id;
              const newVote = change.vote;
              if (oVotes[itemId] !== newVote) {
                voteChanges++;
              }
              oVotes[itemId] = newVote;
            }
            return oVotes;
          });
    
          setVoteChanges(oldCount => oldCount + voteChanges); // rather than having to update it each time, just update it once because state changes can result in re-renders
    
        });
    
      }, []); // you just need this to run once to register the listener, so add []