0

I am creating a component in React using tsx that uses an interface as its props. Like shown below:

export interface ISummaryStats {
    firstName: string,
    lastName: string,
}

export class TestComponent extends React.Component<ISummaryStats> {
    refreshData = async () => {
        const data = await this.getData();
        this.props.firstName = data;
    };
    getData = async () => {
        //Call the API to get the data
        //! API call goes here
        return 'Jimmy';
    }
    public render(): React.ReactNode {
        return (
            <div>
                <h1>
                    {this.props.firstName}
                </h1>
                <h2>
                    {this.props.lastName}
                </h2>
                <button onClick={this.refreshData}>Click me</button>
            </div>
        );
    }
}

What I am trying to do is create a button that calls my API to see if there has been any changes to the data. If so, I want to update the display. However, with the current code I get the following error: Cannot assign to 'firstName' because it is a read-only property.

I am not that experience with interfaces, should I be storing the props values in an object when the component loads so that I can modify that instead of trying to modify the props or is there a different method?

1 Answer 1

1

In React, properties are read only. Use state and setState to allow changing values, as outlined in the docs: https://reactjs.org/docs/state-and-lifecycle.html#adding-local-state-to-a-class

setState triggers a rerender of the component, updating the UI. That's the reason for this pattern.

When using typescript, the first generic type is the type of properties, the second is the type of state.

export interface ISummaryStats {
  firstName: string;
  lastName: string;
}

export class TestComponent extends React.Component<
  ISummaryStats, // type of props
  ISummaryStats // type of state
> {
  constructor(props) {
    super(props);
    this.state = props;
  }
  refreshData = async () => {
    const data = await this.getData();
    this.setState({ firstName: data });
  };
  getData = async () => {
    return 'Jimmy';
  };
  public render(): React.ReactNode {
    return (
      <div>
        <h1>{this.state.firstName}</h1>
        <h2>{this.state.lastName}</h2>
        <button onClick={this.refreshData}>Click me</button>
      </div>
    );
  }
}

Stackblitz: https://stackblitz.com/edit/react-ts-8htues?file=App.tsx

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

1 Comment

Thank you for the response, that is interesting to know. I appreciate the help :)

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.