以 `new` 关键字作为参数的 useState
useState with `new` keyword as parameter
我正在构建一个单独的服务来处理复杂的事情,该服务是 class,只是为了测试建议,我在 useState
.[=14= 中模拟]
关键是我忘记了构造函数中的 console.log
并意识到 class 构造函数在组件重新渲染时被调用了很多次。这种行为不会导致意想不到的行为或类似的事情,但我问自己为什么会这样,因为我知道在 useState
中声明的东西在它的调用中不会重复,但显然我'我错了导致以下问题的原因。
- 为什么会这样? (我没有找到关于这个具体案例的任何文档)
- 这会影响内存或处理吗? (因为 class 被重新实例化了很多次)
- 垃圾收集器收集那个?
我创建了一个小沙箱来举例说明我在说什么,你可以看到控制台上多次显示“已调用”字样,并一直显示单击按钮。
https://codesandbox.io/s/new-class-inside-usestate-w9et3?file=/src/App.js
这是一个常见的错误,在 React 文档中没有明确提及。
在每个渲染 函数组件的主体上执行。
从构造函数中记录日志是预期的行为,因为编写这样的代码:
const [example] = useState(new Foo());
每次渲染都会调用 new Foo()
的结果,是的,尽管 useState
钩子没有考虑它的结果。
因此您希望 lazy initial 像您希望的那样被调用一次:
const [example] = useState(() => new Foo());
The initialState
argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render.
Cus useState(/* whatever expression here */)
还是和JS表达。与 React 无关,这只是 JS 的工作方式,parens ()
中的内容将始终求值。
让我们把 useState
放在一边,想想一些 randomFunction()
,如果你这样做:
setInterval(() => {
randomFunction(new RandomClass());
}, 1000)
RandomClass
会每1秒实例化一次吗?当然会。
同样的事情发生在 React 中。
function MyApp() {
const [myClass, setMyClass] = useState(new RandomClass())
// ...
}
每次 <MyApp />
获得 re-rendered 时,函数必须 re-run,因此必须 RandomClass()
重新 new
。误导你的是useState()
的效果。它采用在 parens 中传递的表达式,因为它是 初始值 在 第一次渲染 时,并将丢弃在后续 re-render 中传递的任何内容。但该表达式仍然有效。
它只是一个表达式,计算结果为 class 的一个实例。碰巧构造函数也记录了一些数据。可以通过使用 iife 来复制相同的行为,即 useState((function(){console.log("Called")})());
。这并不一定意味着它将为您的状态设置一个 class 的新实例,因为它已经在您的组件第一次呈现时设置。
这个理论可以在useEffect
中得到检验
React.useEffect(()=>{
console.log(exemple === exemple)
})
您会看到它 returns 为真,因为它是对同一个 class 的引用,并且没有发生状态更改。在此设置中对您的应用的影响是时间复杂度增加,因为它会在每次渲染发生时实例化一个新的 class。
我正在构建一个单独的服务来处理复杂的事情,该服务是 class,只是为了测试建议,我在 useState
.[=14= 中模拟]
关键是我忘记了构造函数中的 console.log
并意识到 class 构造函数在组件重新渲染时被调用了很多次。这种行为不会导致意想不到的行为或类似的事情,但我问自己为什么会这样,因为我知道在 useState
中声明的东西在它的调用中不会重复,但显然我'我错了导致以下问题的原因。
- 为什么会这样? (我没有找到关于这个具体案例的任何文档)
- 这会影响内存或处理吗? (因为 class 被重新实例化了很多次)
- 垃圾收集器收集那个?
我创建了一个小沙箱来举例说明我在说什么,你可以看到控制台上多次显示“已调用”字样,并一直显示单击按钮。 https://codesandbox.io/s/new-class-inside-usestate-w9et3?file=/src/App.js
这是一个常见的错误,在 React 文档中没有明确提及。
在每个渲染 函数组件的主体上执行。 从构造函数中记录日志是预期的行为,因为编写这样的代码:
const [example] = useState(new Foo());
每次渲染都会调用 new Foo()
的结果,是的,尽管 useState
钩子没有考虑它的结果。
因此您希望 lazy initial 像您希望的那样被调用一次:
const [example] = useState(() => new Foo());
The
initialState
argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render.
Cus useState(/* whatever expression here */)
还是和JS表达。与 React 无关,这只是 JS 的工作方式,parens ()
中的内容将始终求值。
让我们把 useState
放在一边,想想一些 randomFunction()
,如果你这样做:
setInterval(() => {
randomFunction(new RandomClass());
}, 1000)
RandomClass
会每1秒实例化一次吗?当然会。
同样的事情发生在 React 中。
function MyApp() {
const [myClass, setMyClass] = useState(new RandomClass())
// ...
}
每次 <MyApp />
获得 re-rendered 时,函数必须 re-run,因此必须 RandomClass()
重新 new
。误导你的是useState()
的效果。它采用在 parens 中传递的表达式,因为它是 初始值 在 第一次渲染 时,并将丢弃在后续 re-render 中传递的任何内容。但该表达式仍然有效。
它只是一个表达式,计算结果为 class 的一个实例。碰巧构造函数也记录了一些数据。可以通过使用 iife 来复制相同的行为,即 useState((function(){console.log("Called")})());
。这并不一定意味着它将为您的状态设置一个 class 的新实例,因为它已经在您的组件第一次呈现时设置。
这个理论可以在useEffect
React.useEffect(()=>{
console.log(exemple === exemple)
})
您会看到它 returns 为真,因为它是对同一个 class 的引用,并且没有发生状态更改。在此设置中对您的应用的影响是时间复杂度增加,因为它会在每次渲染发生时实例化一个新的 class。