React Hooks渲染两次

时间:2019-10-29 07:50:09

标签: reactjs react-hooks rerender

我定义了一个场景:我们有一个使用父项的道具及其自身状态的组件。

有两个组件DC和JOKER,下面是我的步骤:

  1. 单击DC的按钮
  2. DC setCount
  3. JOKER将使用旧状态进行渲染
  4. 运行useEffect和setCount
  5. JOKER再次渲染

enter image description here

我想问一下为什么JOKER渲染两次(步骤3和5),而第一个渲染浪费了性能。 我只是不想执行步骤3 如果在类组件中,我可以使用componentShouldUpdate来避免它。但是胡克斯有同样的东西吗?

下面的我的代码,或打开此网站https://jsfiddle.net/stephenkingsley/sw5qnjg7/

import React, { PureComponent, useState, useEffect, } from 'react';

function JOKER(props) {
  const [count, setCount] = useState(props.count);
  useEffect(() => {
    console.log('I am JOKER\'s useEffect--->', props.count);
    setCount(props.count);
  }, [props.count]);

  console.log('I am JOKER\'s  render-->', count);
  return (
    <div>
      <p style={{ color: 'red' }}>JOKER: You clicked {count} times</p>
    </div>
  );
}

function DC() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => {
        console.log('\n');
        setCount(count + 1);
      }}>
        Click me
      </button>
      <JOKER count={count} />
    </div>
  );
}

ReactDOM.render(<DC />, document.querySelector("#app"))

3 个答案:

答案 0 :(得分:32)

这是StrictMode的故意功能。这只会发生在 开发,并有助于发现意外的副作用 渲染阶段。我们只对带有挂钩的组件执行此操作,因为 更有可能在错误的地方意外产生副作用。 -gaearon commented on Mar 9, 2019

答案 1 :(得分:0)

我不确定我是否理解您的问题,但是可以。

<DC />组件更改状态时,它将新的状态值count传递给组件Joker。此时,将重新渲染组件,以解决第一个更改。

然后将效果绑定到props.count更改;

  useEffect(() => {
    console.log('I am JOKER\'s useEffect--->', props.count);
    setCount(props.count); 
  }, [props.count]);// <-- This one

哪个在组件从组件DC获取新值时触发。它将自身Joker的状态设置为props.count,这将导致组件重新呈现。

然后,您会得到以下输出:

I am JOKER's  render--> 1 // Initial render where Joker receives props from DC
index.js:27 I am JOKER's useEffect---> 2 // The hook runs because props.count changed
index.js:27 I am JOKER's  render--> 2 // Joker rerenders because its state updated.

答案 2 :(得分:0)

如果我们只想对componentShouldUpdate做同样的事情,则可以使用useMemo。

Traceback (most recent call last):
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\backends\oracle\base.py", line 47, in <module>
    import cx_Oracle as Database
ModuleNotFoundError: No module named 'cx_Oracle'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\u532246\appdata\local\programs\python\python38-32\Lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "c:\users\u532246\appdata\local\programs\python\python38-32\Lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\core\management\commands\runserver.py", line 109, in inner_run
    autoreload.raise_last_exception()
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\utils\autoreload.py", line 77, in raise_last_exception
    raise _exception[1]
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\core\management\__init__.py", line 337, in execute
    autoreload.check_errors(django.setup)()
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\apps\registry.py", line 114, in populate
    app_config.import_models()
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\apps\config.py", line 211, in import_models
    self.models_module = import_module(models_module_name)
  File "C:\Users\u532246\Envs\test\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\Users\u532246\Desktop\skripsi\Django-master\polls\models.py", line 6, in <module>
    class Question(models.Model):
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\models\base.py", line 117, in __new__
    new_class.add_to_class('_meta', Options(meta, app_label))
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\models\base.py", line 321, in add_to_class
    value.contribute_to_class(cls, name)
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\models\options.py", line 204, in contribute_to_class
    self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\__init__.py", line 28, in __getattr__
    return getattr(connections[DEFAULT_DB_ALIAS], item)
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\utils.py", line 201, in __getitem__
    backend = load_backend(db['ENGINE'])
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\utils.py", line 110, in load_backend
    return import_module('%s.base' % backend_name)
  File "C:\Users\u532246\Envs\test\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\Users\u532246\Envs\test\lib\site-packages\django\db\backends\oracle\base.py", line 49, in <module>
    raise ImproperlyConfigured("Error loading cx_Oracle module: %s" % e)
django.core.exceptions.ImproperlyConfigured: Error loading cx_Oracle module: No module named 'cx_Oracle'

单击按钮时,JOKER不会再次呈现。