为何React中简单的useState初始化操作无法生效?
为什么
playerCount始终显示0? 核心原因
useState初始值仅计算一次
const [playerCount, setPlayerCount] = useState(players.length);这行代码里,players.length只在组件第一次挂载时执行一次。初始状态下players是空数组,所以playerCount的初始值被设为0,之后哪怕players通过axios请求更新了,playerCount的状态也不会自动同步——因为没有任何代码触发setPlayerCount去更新它。移除useEffect依赖数组也无法解决问题
哪怕让useEffect每次渲染都重新请求数据更新players,但只要没写players变化时更新playerCount的逻辑,playerCount就永远停留在初始的0值。
解决方案
方案1:直接使用players.length(推荐)
既然playerCount就是players的长度,属于衍生状态,完全不需要单独存为state,直接在JSX里用players.length就行,既简单又不会出现同步问题:
return ( <div> <p>{`This is how many there are: ${players.length}`}</p> </div> );
方案2:用useEffect同步playerCount
如果一定要单独维护playerCount状态,可以加一个监听players的useEffect,在players变化时更新它:
import React, { useState, useEffect } from "react"; import axios from "axios"; function App() { const [players, setPlayers] = useState([]); const [playerCount, setPlayerCount] = useState(0); const getAllPlayersUrl = "http://localhost:5087/api/GetAllPlayers"; useEffect(() => { axios.get(getAllPlayersUrl).then((response) => { setPlayers(response.data); }); }, []); // 监听players变化,同步更新playerCount useEffect(() => { setPlayerCount(players.length); }, [players]); return ( <div> <p>{`This is how many there are: ${playerCount}`}</p> </div> ); } export default App;
方案3:用useMemo缓存衍生值
如果后续有更复杂的衍生逻辑(不只是简单的长度计算),可以用useMemo缓存计算结果,避免每次渲染都重复计算:
import React, { useState, useEffect, useMemo } from "react"; import axios from "axios"; function App() { const [players, setPlayers] = useState([]); const getAllPlayersUrl = "http://localhost:5087/api/GetAllPlayers"; useEffect(() => { axios.get(getAllPlayersUrl).then((response) => { setPlayers(response.data); }); }, []); // 用useMemo缓存衍生值,仅在players变化时重新计算 const playerCount = useMemo(() => players.length, [players]); return ( <div> <p>{`This is how many there are: ${playerCount}`}</p> </div> ); } export default App;
总的来说,对于这种能从现有状态直接计算出来的衍生值,优先选择方案1或方案3,避免维护额外的state带来的同步问题。
内容的提问来源于stack exchange,提问作者HeyLameRobin
相关产品推荐
相关产品推荐

