简体   繁体   中英

react typescript with function passed as prop, but can't access

I am making a simple toggle button with react + typescript. I want to practice some complex feature by passing function as prop to child component. I remember 'this.props' allows me to access all props passed to child in typescript. So if I define a function in parent, I should be able to call the function in child, right?

But I got the below error. Can someone please give me a helping hand? Thank you.

Error:

(property) React.DOMAttributes.onClick?: React.MouseEventHandler | undefined Type '(checked: boolean) => void' is not assignable to type 'MouseEventHandler'. Types of parameters 'checked' and 'event' are incompatible. Type 'MouseEvent' is not assignable to type 'boolean'.ts(2322)

Code:

src/

import React from 'react';
import ReactDOM from 'react-dom';
import Switch from './Switch';

interface State {
  buttonOn: boolean;
}

class App extends React.PureComponent<{}, State> {
  public state: State = {
    buttonOn: false,
  };

  onChange = (checked: boolean) => this.setState({ buttonOn: checked });

  render() {
    return (
      <div>
        <Switch
          checked={this.state.buttonOn}
          onChange={(checked) => this.onChange(!checked)}
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app')!);

src/Switch/

import React from 'react';
import './index.css';

interface Props {
  checked: boolean;
  onChange: (checked: boolean) => void;
  disabled?: boolean;
}

export default class Switch extends React.PureComponent<Props> {
  render() {
    return (
      <div>
        <div onClick={this.props.onChange} /> {/* error here */}
      </div>
    );
  }
}

so you have 2 options... Either

  1. Do it like this where this.props.onChange is being returned by the onClick lambda function. You can also wrap this in curly braces if you want
export default class Switch extends React.PureComponent<Props> {
  render() {
    return (
      <div>
        <div onClick={(e) => this.props.onChange} /> {/* error here */}
      </div>
    );
  }
}

or;

  1. Change your types... It's always worth hovering over a property such as onClick to understand the function signature as well as the type of arguments that are being passed in.
# src/App.tsx
import React from "react";
import Switch from "./Switch";

interface State {
  buttonOn: boolean;
}

class App extends React.PureComponent<{}, State> {
  public state: State = {
    buttonOn: false
  };

  onChange = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
    console.log(event);
  };

  render() {
    return (
      <div>
        <Switch checked={this.state.buttonOn} onChange={this.onChange} />
      </div>
    );
  }
}

export default App;

Then in the Switch:

# src/Switch.tsx

import React from "react";

interface Props {
  checked: boolean;
  onChange: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
  disabled?: boolean;
}

export default class Switch extends React.PureComponent<Props> {
  render() {
    return (
      <div>
        <button onClick={this.props.onChange}> Hello world </button>
      </div>
    );
  }
}

I wrote a Codesandbox playground here so you can test it out yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM