Ian Vink
Ian Vink

Reputation: 68780

ReactJS Updating display

Newbie question.

I'm learning ReactJS in Typescript and am coming from an AngularJS background (trying to unlearn AngularJS).

The code below runs and displays the props.compiler. When I tap the H1, the handler fires but the React code doesn't update the display like it would in AngularJS.

What am I missing?

export interface IHelloProps {
  compiler: string;
  framework: string;
}

export class Hello extends React.Component<IHelloProps> {
  constructor(props: IHelloProps) {
    super(props);
    this.x = props.compiler;
  }

  private x: string;

  get Name(): string {
    return this.x;
  }

  set Name(value: string) {
    this.x = value;
  }

  render() {
    return <h1 onClick={this.handler}>Hello from {this.Name}!</h1>;
  }

  handler = async (t: any) => {
    const resp = await fetch('https://api.github.com');
    const data = await resp.json();
    this.Name = data.current_user_url;
  };
}

Upvotes: 1

Views: 666

Answers (3)

wentjun
wentjun

Reputation: 42556

TypeScript's interface is purely for typechecking. You should not be directly referencing any of its properties.

Instead, I would recommend you to create an interface for your state, which holds the values of current_user_url from your fetch request.

Then, on your click handler, you update the state by calling setState() to re-render the component with the updated state. On important thing to take note, is that you should never mutate state directly.

In order to fully implement TypeScript's typechecking capabilities on your component, you should use provide React.Component with its prop and state type parameters.

I have modified your code such that your component is TypeScript-compliant. Do take note of the new IHelloState interface.

export interface IHelloProps { 
  compiler: string; 
  framework: string; 
}

export interface IHelloState { 
  name: string; 
}

export class Hello extends React.Component<IHelloProps, IHelloState> {

  constructor(props: IHelloProps) {
    super(props);
    this.state = {
      name: '',
    };
  }


  handler = async (t: React.MouseEvent<HTMLButtonElement>)=> {
    const resp = await fetch('https://api.github.com');
    const data = await resp.json();
    this.setState({
      name: data.current_user_url,
    });
  }

  render() {
    const { name } = this.state;

    return <h1 onClick={this.handler}>
             Hello from {name}
        </h1>;
  }

}

You may read more about working with React and TypeScript over here.

Upvotes: 1

Dennis Vash
Dennis Vash

Reputation: 53934

There is no two-way binding like in AngularJS, you need to use setState in order to schedule an update to a component’s state object:

// A bit more React-Class oriented example
class App extends React.Component {
  state = {
    currentUser: this.props.compiler
  };

  handler = async t => {
    const resp = await fetch('https://api.github.com');
    const data = await resp.json();
    this.setState({ currentUser: data.current_user_url });
  };

  render = () => {
    const { currentUser } = this.state;
    return <h1 onClick={this.handler}>Hello from {currentUser}!</h1>;
  };
}
// Original OP class
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      x: props.compiler
    };
  }

  get Name() {
    return this.state.x;
  }
  set Name(value) {
    this.setState({ x: value });
  }

  handler = async t => {
    const resp = await fetch('https://api.github.com');
    const data = await resp.json();
    this.setState({ x: data.current_user_url });
  };

  render = () => {
    return <h1 onClick={this.handler}>Hello from {this.Name}!</h1>;
  };
}

Try reading the Getting Started section which explains it in depth.

Edit Q-58595576-BasicState

Upvotes: 3

Mohit
Mohit

Reputation: 522

In React you don't set the values like you did in your setter function.

React renders the DOM asynchronously by comparing the virtual DOM.

So you need to use setState() to update the state of your DOM.

You can add state in your code and pass it to the React component.

handler = async (t: any)=> {
  const resp = await fetch('https://api.github.com');
  const data = await resp.json();
  this.Name=data.current_user_url;
  this.setState({name:data.current_user_url}); //name being the state variable
}

Hope it helps!!

Upvotes: 2

Related Questions