如何在 React 中将函数与钩子绑定?

Posted

技术标签:

【中文标题】如何在 React 中将函数与钩子绑定?【英文标题】:How can I bind function with hooks in React? 【发布时间】:2019-04-12 09:27:30 【问题描述】:

基本上我们在构造函数中绑定事件处理函数,或者在 React 类组件中将它们作为箭头函数,如下所示

class Test extends Component
  constructor(props)
    super(props);
    this.state =  count:0 ;
    this.setCount = this.setCount.bind(this);
  

  setCount() 
    this.setState(count: this.state.count + 1);
  

  render() 
    return <button onClick=this.setCount>Increase</button>
  

但是在 React v16.7.0 中引入了钩子之后,类组件变成了有状态的函数式组件。

那么如何在函数组件中绑定函数和钩子呢?

【问题讨论】:

没有必要在函数组件中绑定函数,因为你没有使用this 用箭头功能就不需要了 好的,如果我使用带有 mapStateToProps 的 Redux 连接方法。如何访问 this.props 等功能组件中的 props 或仅访问 props? 你只是使用道具...而不是this.props 【参考方案1】:

没有必要在函数组件中绑定函数/回调,因为函数中没有this。在类中,绑定this 很重要,因为我们要确保回调中的this 引用组件的实例本身。但是,在构造函数中执行.bind 具有另一个有用的属性,即在组件的整个生命周期中创建函数一次,并且不会在每次调用render() 时创建新的回调。要使用 React 钩子只初始化一次回调,您可以使用 useCallback

class Foo extends Component 
  constructor(props) 
    super(props);
    this.handleClick = this.handleClick.bind(this);
  

  handleClick() 
    console.log('Click happened');
  

  render() 
    return <Button onClick=this.handleClick>Click Me</Button>;
  

挂钩

function Foo() 
  const memoizedHandleClick = useCallback(
    () => 
      console.log('Click happened');
    ,
    [], // Tells React to memoize regardless of arguments.
  );
  return <Button onClick=memoizedHandleClick>Click Me</Button>;

【讨论】:

谢谢。我不能写像 const memoizedHandleClick = () => console.log('点击发生'); 这样的事件处理函数吗? ? @Think-Twice 是的,你可以。但它会在每次渲染时重新创建处理程序(与在基于类的render() 中使用箭头函数相同)。 好的,什么是useCallback?它是预定义的名称吗? 是的,这是另一个钩子。你读过文档吗?您应该查看有关钩子的整个部分:reactjs.org/docs/hooks-intro.html【参考方案2】:

人们来到 SO 并复制粘贴代码。把这个答案留在这里,这样 React 社区就不会错误地记住所有内容,并可能做不必要的工作。

功能组件

function Foo() 
  const handleClick = function()
    // use function statements to avoid creating new instances on every render
    // when you use `bind` or arrow functions
    console.log('memoizing can lead to more work!')
  ;
  return <Button onClick=handleClick>Click Me</Button>;

提示:查看使用useCallback 时转译了哪些代码,看看是否有必要,然后再将其放入。如果您不确定是否需要它,则可能不需要。为了确保它对你有好处,请对其进行分析。

【讨论】:

【参考方案3】:

您不妨像这样编写上面的组件Foo 并节省一些打字时间。注意 handleClick 周围的语法...它将闭包 handleClick 定义为 Foo 上的一个字段,而不是一个方法。这消除了您在构造函数中使用 bind 覆盖 OBject 的“handleClick”引用的需要。 (另外,如果你只是调用'super',你不需要定义构造函数!)

class Foo extends Component 
  handleClick = () => 
    console.log('Click happened');
  

  render() 
    return <Button onClick=this.handleClick>Click Me</Button>;
  

同样,对于您的原始示例,只需直接声明 state 和 setCount 并简化您的代码:

class Test extends Component
  state = count: 0

  setCount = () => 
    this.setState(count: this.state.count + 1);
  

  render() 
    return <button onClick=this.setCount>Increase</button>
  

【讨论】:

这只是解决类组件绑定问题的另一种方法。 OP 正在询问如何解决功能组件的问题。

以上是关于如何在 React 中将函数与钩子绑定?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 函数组件中不使用 useEffect 钩子获取数据?

如何在 React 中将输入值恢复为默认值 onClick?

如何使用/不使用 useEffect 钩子在 React JS 函数中获取更改的(新)状态值?

如何在 React 中使用带有钩子的生命周期方法?

React 钩子 useRef() 如何在幕后工作?那个参考到底是啥?

如何在 React 中使用钩子预初始化状态?