嵌套对象无限循环

时间:2019-05-13 23:19:34

标签: reactjs react-hooks

为什么在{data:1}都很好的情况下使用{data:{}}会循环吗?

Codesandbox example

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [test, setTest] = useState(true);

  const role = useRole({ data: {} }); // with object { data: 1 } all fine

  useEffect(() => {
    setTest(false);
  }, []);

  return 1;
}

export function useRole({ data }) {
  const [role, roleSet] = useState(false);

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

  return role;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

2 个答案:

答案 0 :(得分:1)

我认为这与javascript的工作方式有关。

在反应中,useEffect默认在每个渲染之后运行。自定义行为的一种方法是通过提供一个列表作为第二个参数。

这样,react方法将在渲染后对照先前渲染中提供的值进行检查,并仅在更改值后调用效果。

这就是问题所在,您可以通过以下示例进行验证:

if(1 === 1) {
    console.log("1 === 1");
}

if({} === {}) {
    console.log("{} === {}");
}

如果运行此命令,您可能会注意到这里的输出仅为1 === 1。那是因为javascript不会将两个空对象视为相等。

由于要提供{ data: {} }并解压缩useRole中的数据值,因此列表中有一个空对象。

我希望有帮助。

答案 1 :(得分:1)

我认为@TvG所说的是当场。对象比较是通过引用完成的。 创建对象时,您在代码中所做的方式将每次都创建新的引用对象。

const role = useRole({ data: {} });

即使您这样做:

let defaultRole = { data: {} }
const role = useRole(defaultRole);

每次都会创建一个新对象。每次渲染时都会重新计算defaultRole的值。

这里可以做的是,React为我们提供了useRef方法,除非明确更改,否则它不会在重新渲染时更改。这是供您阅读的链接:

useRef docs 您可以执行以下操作:

const { useEffect, useState, useRef }  = React


function App() {
  const [test, setTest] = useState(true);
  console.log("running this")
  let baseObj = {
    data: {}
  }
  const roleDefaultValueRef = useRef(baseObj)
  const role = useRole(roleDefaultValueRef.current);
  useEffect(() => {
    setTest(false);
  }, []);

  return 1
}

function useRole({ data }) {
  const [role, roleSet] = useState(false);

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

  return role;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="root"></div>
追问为什么在这种情况下像data = {}这样的对象会起作用。 因此,您的useRole的作用取决于数据。假设您将useRole称为useRole({})

现在在useRole中,您正在从此传递的对象{}中传播数据值 所以这行

export function useRole({ data }) {

// data will be evaluated as undefined and undefined will remain same on //consecutive rerenders and hence the effect will not run 
}

这是将空白对象传递给useRole时它正在运行的原因。

希望这会有所帮助。 理解之后,尝试在useRole中打印数据的值,您一定会理解的:)

1 === 1 //true
undefined === undefined //true
{} === {} // false