14

I'm getting a ts error from my react component. The component is running fine, building etc, however typescript is showing an error inside the ide. Not sure how i need to declare this to remove the error. I've tried to create a setState method inside the component itself, but this was giving even more errors.

Error:(15, 19) TS2605:JSX element type 'Home' is not a constructor function for JSX elements. Property 'setState' is missing in type 'Home'.

"typescript": "^2.3.4",

"react": "^15.5.4",

"react-dom": "^15.5.4",

!----

export class App extends React.Component<Props, State> {
  public state: State
  public props: Props

 constructor(props: Props) {
  super(props)
  this.state = {
    view: <Home />, <<<<
    } 

-- the rest removed for brevity

export class Home extends React.Component<Props, State> {
public state: State;
public props: Props;

constructor(props: Props) {
    super(props)

}
  public render() {
    return <h1>home</h1>
  }
}
4
  • 1
    You should not put a component instance in your state. Instead, you need to put the props of this component in your state and then create it in the render function. Commented Jun 15, 2017 at 13:31
  • oh right, I was essentially binding each view using this.setState({view:<Home />}) and then under the render method just rendering the view like: {this.state.view}. I wanted to use it as a basic router, which, it is working, but generates the ts errors in the ide. Commented Jun 15, 2017 at 13:57
  • 2
    That's not how it should be done. The state needs to stay simple. Never hold components in the state or props Commented Jun 15, 2017 at 14:02
  • ok, so you suggest I use react router or something to manage this? Commented Jun 15, 2017 at 14:05

2 Answers 2

10

Had the same issue, but my problem was that I was importing React wrong.

The correct way to import it when using TypeScript is with import * as React from "react".

Code example:

import * as React from "react"
import ReactDOM from "react-dom"

class App extends React.Component<any, any> {
  render() {
    return (
      <div>Hello, World!</div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById("app"))

Note: <any, any> allows you to use any props and state variables in your React component, but you should usually define those yourself to take advantage of TypeScript's type annotations.

Sign up to request clarification or add additional context in comments.

1 Comment

Or if you have a variable initialState you can do type State = typeof initialState and get all the atomic types
3

Here's an example of how to use the state and render the components:

type HomeProps = {
    text: string;
}
class Home extends React.Component<HomeProps, void> {
    public render() {
        return <h1>{ this.props.text }</h1>
    }
}

type AppState = {
    homeText: string;
}
class App extends React.Component<void, AppState> {
    constructor() {
        super();

        this.state = {
            homeText: "home"
        };

        setTimeout(() => {
            this.setState({ homeText: "home after change "});
        }, 1000);
    }

    render() {
        return <Home text={ this.state.homeText } />
    }
}

As you can see, the props and state objects are always simple, and the rendering method is in charge of creating the actual components.
This way react knows which components are changed and which parts of the DOM tree should be updated.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.