microsoft / ReSub

A library for writing React components that automatically manage subscriptions to data sources simply by accessing them
MIT License
606 stars 52 forks source link

React 18+ in StrictMode: _buildState is not triggered on state change #203

Open vibhorjuntrax opened 2 years ago

vibhorjuntrax commented 2 years ago

I have just made a simple project to learn RESUB with React + Typescript.

Store

@AutoSubscribeStore
class PermissionsStore extends StoreBase {

    private _permissions: string[] = [];

    updatePermissions(permissions: string) {
        this._permissions = this._permissions.concat(permissions);
        this.trigger();
    }

    @autoSubscribe
    getPermissions() {
        return this._permissions;
    }

}

export default new PermissionsStore();

Component

interface AppState {
    permissions: string[],
}

export default class PermissionsComponent extends ComponentBase<any, AppState> {

    getPermissions = async () => {
        PermissionsStore.updatePermissions("loading")
    }

    render() {
        return <React.Fragment>
            {this.state.permissions?.length ? <h4>Loading</h4> : <h4>Not Loading</h4>}
            <button onClick={this.getPermissions}>get Permissons</button>
        </React.Fragment>;
    }

    protected _buildState(props: {}, initialBuild: boolean, incomingState: Readonly<AppState> | undefined): Partial<AppState> | undefined {
        console.log('in build State')
        return {permissions: PermissionsStore.getPermissions()}
    }
}
mikehardy commented 2 years ago

Without specification of versions used and execution environment, and a truly executable example, this doesn't really work as a https://stackoverflow.com/help/minimal-reproducible-example --> https://stackoverflow.com/help/how-to-ask

vibhorjuntrax commented 2 years ago

Without specification of versions used and execution environment, and a truly executable example, this doesn't really work as a https://stackoverflow.com/help/minimal-reproducible-example --> https://stackoverflow.com/help/how-to-ask

Apologies , Actually I just came across ReSub, so I went through documentation and created a react app using create-react-app based on Typescript.

In my component I only have a button which on click I want to change the state. I am using react dev tool in chrome to observe state. but on click of button It doesn't trigger _buildState also on hot reload it does update state in component .

Therefore the values in store are getting updated on click of button but it's not reflected in Component.

Please let me know If I have missed anything.

mikehardy commented 2 years ago

Ok, I've read your comment, I think I understand what you're saying, but without a repro repo or something I don't have the time to build a test app and integrate your code etc. You haven't done the work to help me (or anyone else) reading help you, so I won't hypothesize on what the cause of the problem may be. See links I posted above

deregtd commented 2 years ago

Yeah I don't see why the above wouldn't be working. TBH I haven't used Resub in about a year at this point, though I'm working on a new project that will definitely use it within a few weeks/months. Can you put together a simple zip or something that reproduces the issue when built?

mikehardy commented 2 years ago

I wonder if it's react v18 or similar? I haven't tried that since my execution context is react-native mostly, with one reat-native-web project but it's still on react v17. Either way, totally works for me - resub is still the core state system in that live app and it's working fine :shrug:

vibhorjuntrax commented 2 years ago

Ok, I've read your comment, I think I understand what you're saying, but without a repro repo or something I don't have the time to build a test app and integrate your code etc. You haven't done the work to help me (or anyone else) reading help you, so I won't hypothesize on what the cause of the problem may be. See links I posted above

Please find the repo for the same. Thank you. https://github.com/vibhorjuntrax/ReSub101.git

vibhorjuntrax commented 2 years ago

I wonder if it's react v18 or similar? I haven't tried that since my execution context is react-native mostly, with one reat-native-web project but it's still on react v17. Either way, totally works for me - resub is still the core state system in that live app and it's working fine 🤷

Thanks for this I tried with react 17 and its working fine. This issue is appearing with react 18.

mikehardy commented 2 years ago

Ah ha!

Thanks for this I tried with react 17 and its working fine. This issue is appearing with react 18.

Thanks for testing that hunch. Okay, react v18 just came out and still is not in wide deployment in my usage context (react-native - which is still on 0.69.0-rc.0 - just a release candidate - where they move from react 17 to 18). That explains why this is just coming up now.

I suppose it is time to look at the react release notes / related changes and see what broke ReSub. This won't be a high priority for me unfortunately (see above: not important for my use case) yet but if it sits longer than a few months I'll probably dig in. Otherwise anyone else with domain skills could trace through to see what happened

@deregtd suggest an edit to the issue and pinning it to say "React v18 issue / works on React v17" for future searchers, maybe adding a "help wanted" :pray: :laughing:

berickson1 commented 2 years ago

I checked out the example here. React 18 actually works with ReSub, the issue here is . StrictMode re-runs lifecycle methods to ensure that there's no side-effects, but ReSub relies on call ordering atm. I expect that this could be fixed, but I think there's a clear path here to unblock yourself by removing the wrapper on the app