在状态中使用钩子更新状态时,如何从数组中的对象中提取数据?

时间:2020-04-09 23:58:50

标签: reactjs react-hooks

这是上一篇文章的一部分:What's the React best practice for getting data that will be used for page render?

我正在使用useState([])将对象添加到数组中。每个对象都有一个firstName和一个lastName值。我想将所有名字和姓氏的总和加起来,以获得全部字符数,这样我就可以得到每个名字的平均名字长度。

我目前所给的值是错误的:firstName(100)lastName(106)

值应为6和7

  const [players, setPlayers] = useState([]);
  const [firstNameCount, setFirstNameCount] = useState(0);
  const [lastNameCount, setLastNameCount] = useState(0);

  useEffect(() => {
    setPlayers([]);

    teams.forEach(teamId => {
      axios.defaults.headers.common['Authorization'] = authKey;

      axios.get(endPoints.roster + teamId)
        .then((response) => {
          let teamPlayers = response.data.teamPlayers;
          console.log(response.data.teamPlayers)
          setPlayers(prevPlayers => [...prevPlayers, ...teamPlayers]);
        })
        .catch((error) => {
          console.log(error);
        })
    });
  }, [teams]);

  useEffect(() => {
     players.forEach(player => {
            setFirstNameCount(prevCount => prevCount + player.firstName.length);
            setLastNameCount(prevCount => prevCount + player.lastName.length);
          })
  }, [players]);

如果我将代码更改为此

useEffect(() => {
    setPlayers([]);

    teams.forEach(teamId => {
      axios.defaults.headers.common['Authorization'] = authKey;

      axios.get(endPoints.roster + teamId)
        .then((response) => {
          let teamPlayers = response.data.teamPlayers;
          console.log(response.data.teamPlayers)
          setPlayers(prevPlayers => [...prevPlayers, ...teamPlayers]);

          teamPlayers.forEach(player => {
            setFirstNameCount(prevCount => prevCount + player.firstName.length);
            setLastNameCount(prevCount => prevCount + player.lastName.length);
          })
        })
        .catch((error) => {
          console.log(error);
        })
    });
  }, [teams]);

它大大降低了渲染速度,但我得到:firstName(7),lastName(7),这仍然是错误的。

2 个答案:

答案 0 :(得分:1)

我建议您将团队/玩家的工作搬出您的组件,并移至与该组件分开的商店中,但是无论如何,为什么要设置长度?为什么不只在需要时根据玩家状态来计算?

const sum = values => values.reduce((r, v) => r + v, 0);
const avg = values => sum(values) / values.length;

const avgFirst = avg(players.map(p => p.firstName.length));
const avgLast = avg(players.map(p => p.lastName.length));

我意识到这会使它在每个渲染器上重新计算,但是除非您的玩家列表很大,否则我希望它表现合理。

答案 1 :(得分:0)

好吧,不用为每个增量设置状态,您可以做的是将所有名字和姓氏的长度加起来,然后像这样设置状态:

useEffect(() => {
    setPlayers([]);

    teams.forEach(teamId => {
      axios.defaults.headers.common['Authorization'] = authKey;

      axios.get(endPoints.roster + teamId)
        .then((response) => {
          let teamPlayers = response.data.teamPlayers;
          console.log(response.data.teamPlayers)
          setPlayers(prevPlayers => [...prevPlayers, ...teamPlayers]);

          let firstNameCount = 0;
          let lastNameCount = 0;

          teamPlayers.forEach(player => {
            firstNameCount += player.firstName.length;
            lastNameCount += player.lastName.length;
          })
          setFirstNameCount(prevCount => prevCount + firstNameCount);
          setLastNameCount(prevCount => prevCount + lastNameCount);
        })
        .catch((error) => {
          console.log(error);
        })
    });
  }, [teams]);

让我知道是否有帮助:)