Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是什么导致该组件检测其道具的变化?_Javascript_Reactjs_React Hooks_Use Effect - Fatal编程技术网

Javascript 是什么导致该组件检测其道具的变化?

Javascript 是什么导致该组件检测其道具的变化?,javascript,reactjs,react-hooks,use-effect,Javascript,Reactjs,React Hooks,Use Effect,在下面的最小示例中,父组件具有data属性,并将data.value传递给子组件。我很难理解更新策略到底是怎么回事: const MY_DATAVALUE = { a: 1, b: 2 }; const DATA = { value: MY_DATAVALUE }; function Child(props) { useEffect(() => { console.log("child props changed"); }, [props]); ret

在下面的最小示例中,父组件具有
data
属性,并将
data.value
传递给子组件。我很难理解更新策略到底是怎么回事:

const MY_DATAVALUE = {
  a: 1,
  b: 2
};

const DATA = {
  value: MY_DATAVALUE
};

function Child(props) {
  useEffect(() => {
    console.log("child props changed");
  }, [props]);

  return <h1>Child</h1>;
}

export default function App() {
  const [data, setData] = useState(DATA);

  useEffect(() => {
    console.log("data changed");
  }, [data]);

  useEffect(() => {
    console.log("data.value changed");
  }, [data.value]);

  function handleButtonClick() {
    const newData = {
      value: MY_DATAVALUE
    };
    setData(newData);
  }

  return (
    <>
      <button onClick={handleButtonClick}>Button</button>
      <Child value={data.value} />
    </>
  );
}

const MY_DATAVALUE={
答:1,,
b:2
};
常数数据={
值:我的数据值
};
功能儿童(道具){
useffect(()=>{
console.log(“更改了子道具”);
}[道具];
返回儿童;
}
导出默认函数App(){
const[data,setData]=使用状态(data);
useffect(()=>{
控制台日志(“数据更改”);
},[数据];
useffect(()=>{
console.log(“data.value已更改”);
},[data.value]);
函数handleButtonClick(){
常数newData={
值:我的数据值
};
setData(newData);
}
返回(
按钮
);
}
(见此) 现在,单击按钮时,我认为会发生以下情况:

  • 应用程序的
    handleButtonClick()
    被执行,并且
    数据
    -状态现在指向一个新对象。因此,应用程序的第一个
    useffect
    (检查
    数据
    )触发

  • 但是
    data.value
    仍然包含相同的引用(指向
    MY_DATAVALUE
    ),因此应用程序的第二个
    useffect
    (检查
    data.value
    )不会触发

但是:孩子的
useffect
(检查
props
)触发。为什么呢?根据家长的说法,
data.value
没有改变(否则会触发第二个
useffect

你能给我解释一下,为什么child
useffect
triggers`?我怎样才能知道道具是否“真的”改变了?我需要单独检查所有道具钥匙吗?
谢谢大家!

useffect
如果我们提供的内容不同,依赖项将触发更改。如果我们用不同的值传递相同的引用,或者传递不同的引用,就会发生这种情况

const newData = {
  value: MY_DATAVALUE
};

setData(newData);
数据
现在指的是不同的对象,而
键指的是与上一个值相同的对象

这意味着,此挂钩将触发:

useEffect(() => {
  console.log("data changed");
}, [data]);
虽然这不会触发:

useEffect(() => {
  console.log("data.value changed");
}, [data.value]);
const MY_DATAVALUE = {
  a: 1,
  b: 2
};

// In Parent...

<Child value={MY_DATAVALUE} />

// In Child...

useEffect(() => {
  console.log("child value changed");
}, [props.value]);

到目前为止,这是你在两个方面所解释的

对于子对象,
props
对象是每个渲染上的新引用

因此,此挂钩将始终触发:

useEffect(() => {
  console.log("child props changed");
}, [props]);
虽然此挂钩不会触发:

useEffect(() => {
  console.log("data.value changed");
}, [data.value]);
const MY_DATAVALUE = {
  a: 1,
  b: 2
};

// In Parent...

<Child value={MY_DATAVALUE} />

// In Child...

useEffect(() => {
  console.log("child value changed");
}, [props.value]);
const MY_DATAVALUE={
答:1,,
b:2
};
//在父。。。
//在孩子。。。
useffect(()=>{
console.log(“子值已更改”);
},[props.value]);

我认为这是因为
App
组件的状态作为道具传递给
Child
,而
App
组件通过状态更新重新呈现,因此由于没有对对象内容进行“深入”比较,因此也会重新呈现子组件。我认为您需要使用
useReducer
进行深度状态对象比较。
usemo
useCallback
检查道具的差异。使用效果会在任何更改时触发,尽管它是相同的数据谢谢您的明确解释。尤其是“道具对象是每次渲染的新参考”这句话,让我明白了!一件小事:“如果我们用不同的值传递相同的引用”意味着我们用不同的
原语
值传递相同的引用,对吗?@Raphael,不客气!是的,这就是我的意思,对于对象来说,谈论引用和值会让人困惑
{}==={}
将返回false,而
const a={}
a===a
将返回true;在
原语的情况下,正如您所说的
123==123
将返回true。