Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typings for class component state attribute #2995

Merged
merged 2 commits into from
Aug 19, 2021

Conversation

davwheat
Copy link
Member

@davwheat davwheat commented Jul 31, 2021

Changes proposed in this pull request:

All of our class component instances have a state attribute which is, by default, undefined. This is managed by Mithril itself, but we currently have no way to apply types to it within Flarum.

This PR adds the ability to set typings for this attribute more easily, so that extensions can choose to store the data for their components within this.state more easily.

We generally store component data directly on the this object, but this often ends up polluting the class with lots of data. Storing it under state makes it easier to be typed, especially if data is set dynamically, and it is more friendly to developers coming from other frameworks, such as React.

We might want to consider defaulting this.state to an empty object within our class component. This shouldn't cause any backwards-compatibility issues, but might be better in another PR.

Current method:

class MyComponent extends Component<Record<string, never>> {
  loading!: boolean;
  apiData?: Record<string, unknown>;
  formData!: {
    icon: string,
  };

  oninit() {
    super.oninit(arguments);
    this.loading = true;
    this.formData = {
      icon: "fas fa-blah",
    };
  }

  stopLoading() {
    this.loading = false;
  }

  async fetchApiData() {
    this.apiData = await m.request("https://example.com/endpoint");
  }
}

this.state method:

interface IComponentState {
  loading: boolean;
  apiData?: Record<string, unknown>;
  formData: {
    icon: string;
  }
}

class MyComponent extends Component<Record<string, never>, IComponentState> {
  oninit() {
    super.oninit(arguments);

    this.state = {
      loading: true,
      formData: {
         icon: "fas fa-blah"
      },
    };
  }

  stopLoading() {
    this.state.loading = false;
  }

  async fetchApiData() {
    this.apiData = await m.request("https://example.com/endpoint");
  }
}

Confirmed

  • Frontend changes: tested on a local Flarum installation.

@davwheat davwheat self-assigned this Jul 31, 2021
@davwheat davwheat added this to the 1.0.5 milestone Jul 31, 2021
@davwheat davwheat requested a review from SychO9 August 10, 2021 20:43
@askvortsov1
Copy link
Sponsor Member

Are there benefits to using this.state over this aside from typing? Types on class properties aren't that difficult IMO. I'm hesitant to introduce support for this approach unless we go 100% in and discourage setting properties directly on the component object.

@davwheat
Copy link
Member Author

There isn't any inherent benefit, no.

The reason I added this was because it's part of mithril, like attrs and lifecycle hooks.

I would rather discourage setting values on the class instance itself and instead use state. IMO, it makes it clearer to understand.

@askvortsov1
Copy link
Sponsor Member

I would rather discourage setting values on the class instance itself and instead use state. IMO, it makes it clearer to understand.

I think I agree with this. However, I'm not sure we should make this change now until we're ready to start refactoring core. Maybe we should work on this after the TS refactor?

@davwheat
Copy link
Member Author

I wouldn't want to work on it until we start proper development on 2.0. It'd be a breaking change for extensions that hook into existing component state if we moved it all to a state object.

@askvortsov1
Copy link
Sponsor Member

I wouldn't want to work on it until we start proper development on 2.0. It'd be a breaking change for extensions that hook into existing component state if we moved it all to a state object.

Maybe then we should include this in the 2.0 refactors?

@davwheat
Copy link
Member Author

In my opinion, it'd be better to add it now. It's one extra thing out of the way, and something that extension developers and new core components can use to be ready for 2.0 and reduce the upgrade workload.

@SychO9 SychO9 modified the milestones: 1.0.5, 1.1 Aug 15, 2021
@davwheat davwheat merged commit 7f2e654 into master Aug 19, 2021
@davwheat davwheat deleted the dw/add-component-state branch August 19, 2021 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants