为什么在渲染之间无法记住箭头功能?

时间:2019-06-06 11:44:41

标签: javascript reactjs arrow-functions

您能解释一下为什么handleClick函数总是新的吗?

function Foo() {
  const handleClick = () => {
    console.log('Click happened');
  }

  return <Button onClick={handleClick}>Click Me</Button>;
}

3 个答案:

答案 0 :(得分:6)

请记住,Foo()也是一个JavaScript函数,已在每个渲染器上重新运行。

在该函数中,有一条语句是:

const handleClick = () => {...};

含义:创建一个函数并将其分配给我最近创建的局部变量handleClick。因此,它将在每个渲染器上重新创建。

对性能的影响通常接近于零。但是,如果需要,您可以对此进行优化。

const handleClick = useCallback(()=>{...},[dependencyArray]);

如果该函数取决于可能会更改的变量,则可以将其添加到dependencyArray中,如果其中一个函数发生更改,React将重新创建该函数。否则,它将与上一次创建时保持相同的功能。

From React Hooks FAQ

  

由于在渲染器中创建函数,钩子变慢了吗?

     

不。在现代浏览器中,与封闭类相比,闭包的原始性能没有很大区别,除非在极端情况下。

发件人:https://reactjs.org/docs/hooks-reference.html#usecallback

useCallback()

  

返回一个已记忆的回调。

     

传递内联回调和一系列依赖项。 useCallback将返回回调的记忆版本,仅在其中一个依赖项已更改时才更改。在将回调传递给依赖于引用相等性的优化子组件以防止不必要的渲染(例如,shouldComponentUpdate)时,这很有用。

答案 1 :(得分:4)

() => { console.log('Click happened'); }创建一个新功能。

在调用Foo函数之间,您什么也不做。

因此,每次调用Foo时,都会得到一个新函数。

答案 2 :(得分:1)

由于每次渲染Foo时,它将再次在其中创建所有内容。

// rendering Foo
function Foo() {
  const handleClick = () => {    // instantiated again
    console.log('Click happened');
  }

  const something...     // instantiated again

  return <Button onClick={handleClick}>Click Me</Button>;
}

为避免再次实例化handleClick,可以在组件外部声明它。

const handleClick = () => {    
  console.log('Click happened');
}
function Foo() {              
  return <Button onClick={handleClick}>Click Me</Button>;
}

或者,如果您确实希望将其包含在函数范围内但不实例化,则可以这样做

// rendering Foo
function Foo() {
  const handleClick = useCallback( // not re-defined again, uses old reference
    () => {
      console.log(`Click happened`);
    }
  );

  const something...     // instantiated again

  return <Button onClick={handleClick}>Click Me</Button>;
}

Read about UseCallback here