synacor / preact-i18n

Simple localization for Preact.
BSD 3-Clause "New" or "Revised" License
205 stars 18 forks source link

All translations disappear after any component change its state (preact X) #39

Closed IvanBoho closed 4 years ago

IvanBoho commented 4 years ago

Hello, I have problems with the latest version of preact:

        "preact": "^10.0.4",
        "preact-i18n": "^2.0.0-preactx.2",
        "preact-router": "^3.1.0",

App.tsx

            // @ts-ignore
            <IntlProvider definition={definition}>
                <Router>
                    <Login path="/login"/>
                    <RedirectToLogin path="/"/>
                    <CommonLayout default/>
                </Router>
            </IntlProvider>
        );

Dom event inside login component:

    onFocusInput(name) {
        const {fieldsMarkedAsInvalid} = this.state;
        fieldsMarkedAsInvalid[name] = false;
        this.setState({fieldsMarkedAsInvalid});
    }

After state is updated, all translations disappear. The same thing occures in any component. Downgrade helped me.

AEnterprise commented 4 years ago

thinkered around a bit, this is especially noticable when using preact-router as those load async so have inner updates

but also reproducable with any updating component outside of that

when initially rendering the intl context is correct (using the preact dev tools to test easier) image

after an update this no longer works however and intl goes blank image

when checking the provider itself that has it's props intact image

other non updated components their context does remain intact, not found the oldest version this was introduced in but it seems to be a change in preact itself that did this since this worked fine on 2.0.0-preactx.2 for months in my dev environment

AEnterprise commented 4 years ago

any chance anyone can take a look at this as it makes preact-i18n completely useless?

billneff79 commented 4 years ago

@AEnterprise, we would welcome a PR to fix this issue.

AEnterprise commented 4 years ago

@billneff79 i'd love to help fix it but sadly i have no clue how, i can't reliably reproduce it outside my project in a new project and i have no clue how any of this context stuff works or is parsed around to go looking for it deeper

pl12133 commented 4 years ago

I haven't been able to reproduce this, but if someone could pick up where I left off it would be very helpful in fixing this issue if it still exists:

https://jsfiddle.net/0xfp5tv1/1/

pl12133 commented 4 years ago

I've managed to reproduce this now, it seems that loading the dictionary asynchronously causes an issue. When the IntlProvider has props of definition={undefined} on it's first render, the stale value will eventually overwrite the new value after a child component calls setState.

Reproduction: https://jsfiddle.net/k8e3fm0n/

Workaround: Add a key={definition} prop to your IntlProvider.

Internally, the child component ends up with a condition of component.context !== component._globalContext which may imply an issue in the diff algorithm for Preact but I'm still investigating.

I'm not sure if there is anything to be done here so I'll follow up in either preactjs/preact or synacor/preact-context-provider.

pl12133 commented 4 years ago

Fixed by a451350 and released in 2.1.1-preactx.

Reproduction fixed: https://jsfiddle.net/xyL04bzm/1/