在React中作为参数传递的参数化函数的奇怪行为

时间:2018-09-19 18:59:12

标签: reactjs typescript

我可能在这里看不到一些明显的东西,但是我对此很不满意。

我有一个功能

public handleTest = (testNum: number) => {
    console.log(testNum);
  };

还有以下情况:我有一个组件要传递给该函数,以便在onCLick事件中进一步使用它。

<Controls handleTest={() => this.handleTest}>
 <Button label="Test1" clicked={() => this.handleTest(42)} />
</Controls>

子组件如下:

interface IProps {
  handleTest: (type: number) => void;
}

class Controls extends React.Component<IProps, {}> {
  public render() {
    const {
      handleTest
    } = this.props;

return (
  <React.Fragment>
    {this.props.children}
    <button onClick={handleTest(42)} label="Test2" />
  </React.Fragment>
);
 }
}

这种情况的有趣之处在于,在使用Test2按钮的情况下,似乎无法识别记录对象时传递给它的参数-

Object { dispatchConfig: {…}, _targetInst: {…}, nativeEvent: click, type: "click", target: button.sc-bwzfXH.gonlMM, currentTarget: button.sc-bwzfXH.gonlMM, eventPhase: 3, bubbles: true, cancelable: true, timeStamp: 689, … }

对于Test1,一切正常。我想知道我在做什么错,是打字稿弄乱了我的东西还是我的一些错误

2 个答案:

答案 0 :(得分:1)

这是因为在初始化<Controls />组件时,要发送的功能是这样的:

() => this.handleTest

因此在button Test2中,您没有执行任何操作,因为最后一个函数只是返回了一个函数

因此,如果您要解决此问题:

<Controls handleTest={(number) => this.handleTest(number)}>
 <Button label="Test1" clicked={() => this.handleTest(42)} />
</Controls>

如果在渲染<Controls />时以这种方式进行操作,则将执行您的函数,而不是在用户单击它时执行。要解决此问题,您需要以以下方式进行更改:

<React.Fragment>
  {this.props.children}
  <button onClick={()=>handleTest(42)} label="Test2" />
</React.Fragment>

要优化,只需发送功能。这是功能注入

<Controls handleTest={this.handleTest}>
   <Button label="Test1" clicked={() => this.handleTest(42)} />
</Controls>

答案 1 :(得分:0)

您正在将函数调用传递给处理程序,仅当您使用原始函数代替函数时,这才起作用。

<button onClick={handleTest(42)} label="Test2" />代替

<button onClick={() => handleTest(42)} label="Test2" />

如果<button onClick={handleTest(42)} label="Test2" />如下所示,

handleTest将起作用:

public handleTest = (testNum: number) => () => {
  console.log(testNum);
};

编辑:当您需要将外部参数注入到处理程序函数中时,我实际上建议使用第二种方法使用处理程序。通过声明一个处理程序 {() => doSomething()},每次渲染组件时,处理函数都会再次初始化。

无论如何,在大多数情况下,这只是一个很小的优化。