简体   繁体   中英

React component throwing TypeScript error for function passed in as prop

I have a Class based React Component that accepts a function as a prop.

The component was originally a stateless functional component that accepted the same function without any TypeScript errors.

Now that I've converted it to a class component I'm getting an error when I call the function: Property 'onRouteChange' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' Property 'onRouteChange' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'

As well as an error when I de-structure it in the props: Property 'onRouteChange' is missing in type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' but required in type '{ onRouteChange: any; }'. Property 'onRouteChange' is missing in type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' but required in type '{ onRouteChange: any; }'.

I initially tried to define it in the types declaration at the top of the file but that's not working either.

Component

type SignInState = {
  signInEmail: string,
  signInPassword: string
}

class SignIn extends Component<{}, SignInState> {
  constructor(props: {}){
    super(props);
    this.state = {
      signInEmail: '',
      signInPassword: ''
    }
  }

  onEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      this.setState({ signInEmail: e.target.value })
  }

  onPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    this.setState({ signInPassword: e.target.value })
  }

  onSubmitSignIn = () => {
    // fetch()
    console.log(this.state);
// TS Error: Property 'onRouteChange' does not exist
    this.props.onRouteChange('home');
  }
  
  render() {
// TS Error: Property 'onRouteChange' is missing in type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' 
    const { onRouteChange } : { onRouteChange: any} = this.props

    return (
      <Container>
        <Main>
          <Form>
            <Fieldset>
              <SignInTitle>Sign In</SignInTitle>
              <EmailAddressSection>
                <Label>Email</Label>
                <EmailInput />
              </EmailAddressSection>
              <PasswordSection>
                <Label>Password</Label>
                <PasswordInput />
              </PasswordSection>
            </Fieldset>
            <div>
              <SignInButton
                onClick={this.onSubmitSignIn}
                type="submit"
                value="Sign in"
              />
            </div>
            <AccountOptionsSection>
              <AccountOption onClick={() => onRouteChange("register")}>
                Register
              </AccountOption>
            </AccountOptionsSection>
          </Form>
        </Main>
      </Container>
    );
  }
};

export default SignIn;
class SignIn extends Component<{}, SignInState> 

The first param to Component type is props type, and you have not defined it, therefore the error.

Define a interface,

interface ISignInProp {

onRouteChange:any
}

and pass it to your Component

class SignIn extends Component<ISignInProp , SignInState> 

Create a type or an interface for your props just as you did with your state.

Props Interface

// interface over type literal
interface IProps { 
 onRouteChange: (param: string) => void
}

Avoid Typing to any

Try to avoid typing something to any . You are basically telling typescript this has no type. That defeats the purpose of TS. If you truly do not know, type it to unknown .

But, you are passing a string home so you have some information on it that you can use to type it a little better.

Here, I am guessing onRouteChange is a function that accepts one parameter of type string and returns nothing (does a side effect). You can update this accordingly.

Typing Your Component Props

You do exactly what you did with your state type (prefer interface over types).

class SignIn extends Component<IProps, IState>

Now you should not have to type onRouteChange when you destructure it.

const { onRouteChange } : { onRouteChange: any} = this.props

becomes

const { onRouteChange } = this.props

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