React Hooks-useCallback性能

时间:2019-12-11 07:33:59

标签: reactjs react-hooks

我正在用React Hooks编写我的产品,是的,我刚刚接触它。

今天我对useCallback的性能进行了数学计算。这使我考虑了很多使用useCallback或不使用的情况。

看看。众所周知,useCallback可以提高性能。

function MainScreen() {
  const [email, setEmail] = useState("");
  const [pwd, setPwd] = useState(""):

  const onAuthenticate = useCallback(() => {
    MyApi.authenticate(email, pwd);
  }, [email, pwd]);

  return <div>
    <MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
  </div>;
}

在上面的示例中,假设有两个电子邮件和密码输入,然后MyCustomButton将在电子邮件或密码更改的所有时间呈现。我尝试使用useCallback来减少渲染次数,但对我而言,这还不够好。

后来,我想出了一种方法,取出依赖项中的电子邮件和密码,并使用useRef来保存电子邮件和密码的值。

function MainScreen() {
  const [email, setEmail] = useState("");
  const [pwd, setPwd] = useState(""):

  const emailRef = useRef(email);
  const pwdRef = useRef(pwd);

  const onAuthenticate = useCallback(() => {
    MyApi.authenticate(emailRef.current, pwdRef.current);
  }, []);

  useEffect(() => {
    emailRef.current = email;
    pwdRef.current = pwd;
  }, [email, pwd]);

  return <div>
    <MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
  </div>;
}

采用这种方法,每次更改电子邮件或密码时,它都会停止在MyCustomButton中呈现。

实际上在性能和成本上更好吗?你们觉得呢?

感谢分享。

3 个答案:

答案 0 :(得分:0)

我在您的代码中看到的问题与useCallback无关,而与useState无关。

反应(无论是否使用挂钩)的经验法则是,状态对显示的内容有直接影响。如果您修改状态,则意味着应重新渲染组件。

此基本原理是使您在使用useState时重新呈现组件的原因。 React假设emailpassword会改变组件的外观,因此,只要您更改其值之一,它就会被重新渲染。

如果您实际上并未在email中使用pwdMyCustomButton,那么使用useRef而不是useState更有意义。

但是,在第二个代码示例中使用它的方式没有多大意义:您将useStateuseRef组合在一起,以便email发生变化时(使用setEmail时会出现这种情况,然后使用相同的值更新ref。唯一的好处是不会每次都重新构造onAuthenticate。

完全跳过useState会更有利,但是从您发布的代码中,实际上很难提出不同的解决方案,因为尚不清楚email和{{ 1}}实际已设置。

答案 1 :(得分:0)

由于您仅执行API调用,因此建议不使用 useCallback()。使其改为正常功能。

您可能正在进行过早的优化。仅当您在应用上执行大量计算并且需要记住您的值时,才应该进行性能优化。

here.可以看到普通函数与使用useCallback()的函数的深入比较。

答案 2 :(得分:0)

在这种情况下,我想使用React.memo而不是useCallback。 使用React.memo来确保该组件不会调用父对象设置的渲染, 一旦组件调用的呈现方式,电子邮件或密码更改了,那么useCallback就不再需要

function MainScreen() {
  const [email, setEmail] = useState("");
  const [pwd, setPwd] = useState(""):

  const onAuthenticate = () => {
    MyApi.authenticate(email, pwd);
  };

  return <div>
    <MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
  </div>;
}
export default React.memo(MainScreen)