【问题标题】:Order of useCallback declaration使用顺序回调声明
【发布时间】:2021-10-08 16:01:40
【问题描述】:

useCallback 函数声明的顺序重要吗?例如:

按此顺序声明的函数:

  1. const aboveFunction = useCallback(()=>{ logCount() },[logCount])

  2. const logCount = useCallback(()=>{ console.log(count) },[count])

  3. const belowFunction = useCallback(()=>{ logCount() },[logCount])

注意aboveFunctionbelowFunction 指的是同一个logCount。 在我们调用setCount(2)之后,

aboveFunction() -> logCount() -> count // 0,在哪里

belowFunction() -> logCount() -> count // 2

https://codesandbox.io/s/react-hooks-counter-demo-forked-7mofy?file=/src/index.js

/**
  Click increment button until count is 2, then click 
  Above and Below button and check console log
 * Even though the count value is > 0, aboveIncrement console.log(count) still gives 0
 */

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

import "./styles.css";

function App() {
  const [count, setCount] = useState(0);

  /** Assuming all the functions below do some intensive stuffs to justify useCallback */
  const aboveFunction = useCallback(() => {
    // ...do other intensive stuff
    logCount("Above count:"); // Above count: 0
  }, [logCount]);

  const logCount = useCallback(
    (str) => {
      // ...do other intensive stuff
      console.log(str, count);
    },
    [count]
  );

  const belowFunction = useCallback(() => {
    // ...do other intensive stuff
    logCount("Below count:"); // Above count: 2
  }, [logCount]);

  return (
    <div className="App">
      <h1>
        Click increment button until count is 2, then click Above/ Below button
        and see console log
      </h1>
      <h2>You clicked {count} times!</h2>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          flexDirection: "column"
        }}
      >
        <button style={{ margin: 10 }} onClick={aboveFunction}>
          Above Increment Function
        </button>
        <button style={{ margin: 10 }} onClick={() => setCount(count + 1)}>
          Increment
        </button>
        <button style={{ margin: 10 }} onClick={belowFunction}>
          Below Increment Function
        </button>
      </div>
    </div>
  );
}

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

很明显,useCallback 声明的顺序对于代码的工作很重要。但是,如果我们这样写 https://codesandbox.io/s/react-hooks-counter-demo-forked-7mofy?file=/src/index1.js

  let logCount;
  const aboveFunction = useCallback(() => {
    logCount("Above count:"); // Above count: 0
  }, [logCount]);

  logCount = useCallback((str) => {
      console.log(str, count);
    }, [count]
  );

  const belowFunction = useCallback(() => {
    logCount("Below count:"); // Above count: 2
  }, [logCount]);

aboveFunction 仍然给出过时的计数值。有没有我遗漏的规则?

是的,这里的解决方法是应用 eslint no-use-before-define。但我想了解为什么 .. 函数在 JavaScript 中没有被提升并且声明的顺序并不重要?

【问题讨论】:

  • “假设下面的所有函数都做了一些密集的工作来证明 useCallback 的合理性” useCallback 不会改变任何关于“密集的工作”的东西。我会说,只需删除该代码中的useCallback()s,但我不明白您到底想要实现什么/为什么首先将它们放在那里

标签: reactjs react-hooks


【解决方案1】:

有没有我遗漏的规则?

您没有错过rule-of-hooks,但是,您错过了no-use-before-define 规则。

你必须使用aboveFunction.上方的logCount函数

在这个附加的图像中

你可以看到,它显示了函数声明的警告。

也许你可以在你的项目中添加es-lint,并确保你也添加了这个pluginno-use-before-define,这样它就会在vs代码中向你显示这些类型的警告。

希望这会有所帮助!

【讨论】:

  • 但是'no-use-before-def'并不是万无一失的,因为你可以看到我的问题的第二部分。
  • 难道函数不是在 JavaScript 中被提升,它们的声明顺序并不重要吗?或者只有当它被包装在 useCallback 中时才有意义?
  • 我们应该避免使用这些类型的hoisting。它不会帮助你。它不会给你任何好处,它只会增加你的痛苦。你也可以在这里查看stackoverflow.com/a/29718445/7348073。但无论如何,这是一个很好的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
相关资源
最近更新 更多