简体   繁体   English

JS中object的锁定行为?

[英]Locking behavior of object in JS?

On every click of increment button:每次单击increment按钮时:
Expectation: current count is logged期望:记录当前count
Reality: initial value of count , ie 3 is logged现实: count的初始值,即 3 被记录

import React, { useState, useEffect } from "react";

function SomeLibrary(props) {
  const [mapState, setMapState] = useState(undefined);

  useEffect(() => {
    console.log("setting map");
    // Run exactly once at mount of component
    setMapState(props.map);
  }, []);

  useEffect(() => {
    if (mapState) {
      mapState.key();
    }
  }, [props]);

  return <div> ... </div>;
}

export default function App() {
  const [count, setCount] = React.useState(3);

  const map = { key: () => {
    console.log("fn", count);
  }};

  return (
    <div>
      Active count: {count} <br />
      <button onClick={() => {
          setCount(count + 1);
        }}
      >
        Increment
      </button>
      <SomeLibrary map={map} />
    </div>
  );
}

Run here跑到这里

Does the object in JS locks the values of variables inside it after initializing? JS中的object初始化后会不会锁住里面变量的值?

I want to know the reason why function in object doesn't use the current value of count whenever invoked but React ref gets the current value in that same scenario我想知道为什么 object 中的 function 在调用时不使用 count 的当前值但 React ref 在同一场景中获取当前值的原因

I don't understand why this works:我不明白为什么会这样:
Replace the map variable with this:将 map 变量替换为:

const [count, setCount] = React.useState(3);
const stateRef = useRef();
stateRef.current = count;

const map = { key: () => {
  console.log("fn", stateRef.current);
}};

Does the object in JS locks the values of variables inside it after initializing? JS中的object初始化后会不会锁住里面变量的值?

No.不。

You're effectively setting state of SomeLibrary with an initial value when it mounts, and never again updating that state, so it continually logs its initial value.您在安装时有效地将 SomeLibrary 的SomeLibrary设置为初始值,并且不再更新该 state,因此它会不断记录其初始值。

const [mapState, setMapState] = useState(undefined);

useEffect(() => {
  console.log("setting map");
  // Run only once at mount of component
  setMapState(props.map); // <-- no other `setMapState` exists
}, []); // <-- runs once when mounting

By simply adding props.map to the dependency array this effect runs only when map updates, and correctly updates state.通过简单地将props.map添加到依赖数组中,此效果仅在map更新并正确更新 state 时运行。

useEffect(() => {
  console.log("setting map");
  // Run only once at mount of component
  setMapState(props.map);
}, [props.map]);

编辑 hardcore-kilby-n0ogv

Notice, however, the state of SomeLibrary is a render cycle behind that of App .但是请注意, SomeLibrary 的SomeLibraryApp之后的渲染周期。 This is because the value of the queued state update in SomeLibrary isn't available until the next render cycle.这是因为 SomeLibrary 中排队的SomeLibrary更新的值在下一个渲染周期之前不可用 It is also an anti-pattern to store passed props in local component state ( with few exceptions ).在本地组件 state 中存储传递的道具也是一种反模式(除了少数例外)。

Why React ref gets the current value in that same scenario?为什么 React ref 在同一场景中获取当前值?

const [count, setCount] = React.useState(3);
const stateRef = useRef();
stateRef.current = count; // <-- stateRef is a stable reference

const map = { key: () => {
  console.log("fn", stateRef.current); // <-- ref enclosed in callback
}};

When react component props or state update, a re-render is triggered.当 react 组件 props 或 state 更新时,会触发重新渲染。 The useRef does not, it's used to hold values between or through render cycles, ie it is a stable object reference. useRef不是,它用于在渲染周期之间或通过渲染周期保存值,即它是一个稳定的 object 参考。 This reference is enclosed in the callback function in the map object passed as a prop.此引用包含在作为道具传递的 map object 中的回调 function 中。 When the count state updates in App a rerender is triggered and stateRef.current = count;count state 在App中更新时,会触发重新渲染并且stateRef.current = count; updates the value stored in the ref, ie this is akin to an object mutation.更新存储在 ref 中的,即这类似于 object 突变。

Another piece to the puzzle is functional components are always rerendered when their parent rerenders.另一个难题是功能组件总是在其父级重新渲染时重新渲染。 The passed map object is a new object when passed in props.通过的map object 是一个的 object 在通过 props 时。

It's this rerendering that allows SomeLibrary to run the second effect to invoke the non-updated-in-state callback mapState.key , but this time the object reference being console logged has been mutated.正是这种重新渲染允许SomeLibrary运行第二个效果来调用非更新状态回调mapState.key ,但是这次控制台记录的 object 引用已经发生了变异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM