如何在 React 中使用钩子绑定函数?

IT技术 javascript reactjs react-native react-hooks
2021-03-25 00:52:52

基本上我们在构造函数中绑定事件处理函数,或者在 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 引入钩子之后,类组件变成了具有状态的功能组件。

那么如何将函数与函数组件中的钩子绑定呢?

3个回答

由于没有thisin 函数,因此无需在函数组件中绑定函数/回调在类中,绑定很重要,this因为我们希望确保this回调中的 引用到组件的实例本身。但是,.bind在构造函数中执行还有另一个有用的特性,即在组件的整个生命周期内创建函数一次,并且不会在每次调用render(). 要使用 React 钩子仅初始化一次回调,您可以使用useCallback.

class

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>;
}
是的,这是另一个钩子。你读过文档吗?你应该查看关于钩子的整个部分:reactjs.org/docs/hooks-intro.html
2021-06-07 00:52:52
好的,什么是 useCallback?它是预定义的名称吗?
2021-06-13 00:52:52
@Think-Twice 是的,你可以。但它会在每个渲染上重新创建处理程序(与在基于类的使用箭头函数相同render())。
2021-06-17 00:52:52
谢谢你。我不能编写像 const memoizedHandleClick = () => { console.log('点击发生'); 这样的事件处理函数吗??
2021-06-20 00:52:52

人们来到 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查看转译了哪些代码,看看是否有必要,然后再将其放入。如果您不确定是否需要它,您可能不需要。并确定它对您有好处,请对其进行分析。

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

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 正在询问如何解决功能组件的问题。
2021-06-03 00:52:52