0

I am learning typescript and was trying to implement a detailList component from Microsoft Fluent UI, but I ran into some trouble:

Type '(ev: React.MouseEvent<HTMLElement>, checked: boolean) => void' is not assignable to type '(event: MouseEvent<HTMLElement, MouseEvent>, checked?: boolean | undefined) => void'.

In the code there was a function called _onChangeCompactMode being referenced when a toggle button is clicked

  private _onChangeCompactMode = (ev: React.MouseEvent<HTMLElement>, checked: boolean): void => {
this.setState({ isCompactMode: checked });

Here is where it's referenced:

  <Fabric>
    <div className={classNames.controlWrapper}>
      <Toggle
        label="Enable compact mode"
        checked={isCompactMode}
        onChange={this._onChangeCompactMode}
        onText="Compact"
        offText="Normal"
        styles={controlStyles}
      />
       ...
  </Fabric>

I fixed this issue by changing this line onChange={this._onChangeCompactMode} to this onChange={() => this._onChangeCompactMode}

I am not sure why this made it work. My understanding is, I passed a function reference. But why wouldn't it work as it is without () =>

Still new here, so constructive feedback is welcomed.

Haytham
  • 23
  • 6

2 Answers2

1

You have to be careful about the meaning of this in JSX callbacks. If you forget to bind this._onChangeCompactModeand pass it to onChange, this will be undefined when the function is actually called. That's why you have to use the arrow function, like you did. Or the _onChangeCompactMode itself has to be an arrow function, like so:

  _onChangeCompactMode = () => {
    // your code
  }

then pass its reference:

onChange={this._onChangeCompactMode}

They should work the same

KienHT
  • 1,098
  • 7
  • 11
0

The problem is because the types don't match. Have a look at the toggle documentation

onChange has the type:

(event: React.MouseEvent<HTMLElement>, checked?: boolean) => void

Note that the checked is optional, but in your implementation it's not. It should work if you make it optional:

private _onChangeCompactMode = (ev: React.MouseEvent<HTMLElement>, checked?: boolean): void => {
this.setState({ isCompactMode: checked ?? false });

Make sure to add a default now that checked is optional, like I did with checked ?? false

Philip Feldmann
  • 7,887
  • 6
  • 41
  • 65