反应:如果useState被更新,怎么也不能同时不对其进行更新?

问题描述 投票:2回答:2

我有一个反应代码

  • 设置empty state
  • fills状态
  • 一旦填充此状态,它renders一些图像
  • 此图像然后触发onLoad事件
  • 此onLoad事件然后调用一个function,该reads是初始的state
  • 但是此状态为empty

怎么可能?如果该函数被调用,则意味着该状态不再为空

https://codesandbox.io/embed/ecstatic-lake-9rydu?fontsize=14&hidenavigation=1&theme=dark

代码

import React, { useRef, useState, useEffect } from "react";
import styled from "@emotion/styled";

const useMyHook = (virtual_structure, setVirtual_structure) => {
  useEffect(() => {
    console.log("virtual_structure is updated!");
    console.log(virtual_structure);
    console.log("____virtual_structure is updated!");
  }, [virtual_structure]);

  const refs = useRef([]);

  const createStructure = () => {
    console.log("virtual_structure, is it empty?");
    console.log(virtual_structure);
  };

  useEffect(() => {
    createStructure();
  }, []);

  const assignRef = r =>
    r && (refs.current.includes(r) || refs.current.push(r));

  return [assignRef, createStructure];
};

export default function App() {
  const [virtual_structure, setVirtual_structure] = useState([]);

  const [assignRef, updateGrid] = useMyHook(
    virtual_structure,
    setVirtual_structure
  );

  useEffect(() => {
    const temp_structure = Array.from({ length: 4 }, () => ({
      height: 0,
      cells: []
    }));
    temp_structure[0].cells = Array.from({ length: 10 }, () => {
      const rand = Math.random();
      const r = rand > 0.1 ? parseInt(500 * rand) : parseInt(500 * 0.1);
      return {
        height: "",
        el: (
          <div ref={assignRef}>
            <Image
              alt=""
              onload={updateGrid}
              num=""
              src={`https://picsum.photos/200/${r}`}
            />
          </div>
        )
      };
    });

    setVirtual_structure(temp_structure);
  }, []);

  return (
    <Container>
      {virtual_structure.map((col, i) => (
        <div key={`col${i}`}>
          {col.cells && col.cells.map((cell, j) => <>{cell.el}</>)}
        </div>
      ))}
    </Container>
  );
}

const Image = ({ alt, onload, num, src }) => (
  <>
    <Label>{num}</Label>
    <Img src={src} alt={alt} onLoad={onload} />
  </>
);

const Img = styled.img`
  border: 1px solid #000;
  height: min-content;
  margin: 0;
  padding: 0;
`;
const Label = styled.div`
  position: absolute;
`;

const Container = styled.div`
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  background: #ccc;
  align-content: center;

  div {
    flex: 1;

    div {
      color: #fff;
      font-weight: 700;
      font-size: 32px;
      margin: 4px;
    }
  }
`;

和console.log

virtual_structure is updated!
index.js:27 Array(0)length: 0__proto__: Array(0)
index.js:27 ____virtual_structure is updated!
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure is updated!
index.js:27 Array(4)0: {height: 0, cells: Array(10)}1: {height: 0, cells: Array(0)}2: {height: 0, cells: Array(0)}3: {height: 0, cells: Array(0)}length: 4__proto__: Array(0)
index.js:27 ____virtual_structure is updated!
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 Array(0)length: 0__proto__: Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 []length: 0__proto__: Array(0)
index.js:27 virtual_structure, is it empty?
index.js:27 []
javascript reactjs react-hooks react-state
2个回答
2
投票
由于closures而发生。

0
投票
正如@ Dennis-vash答案中所说,“闭包”冻结了作用域函数中的useState变量,因此该函数从不会看到该变量的当前(更新)值
© www.soinside.com 2019 - 2024. All rights reserved.