synacor / preact-i18n

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

Usage with React #9

Closed mhamann closed 6 years ago

mhamann commented 7 years ago

This is a super awesome library, but it seems like it could be usable with React with little effort. Maybe you'd consider adding support?

billneff79 commented 7 years ago

A consuming application could fairly easily make any preact-compatible library work with React. Rather than trying to make each preact-targeted library work with React, you might want to investigate that compatibility layer. For this particular library, you probably just need to modify the prototype of Component.render() such that it knows how to handle render(props, state,context). You are basically looking for the inverse of preact-compat.

While we could modify this repo to work with React out of the box, since we don't target/test with it, I would be concerned about it working long term and things that we don't consider as breaking changes being breaking changes for React consumers.

developit commented 7 years ago

Supporting React would require adding contextTypes, which seems like a bit of a loss given they aren't needed by Preact. Also it would require using React.Children.only() here.

It's probably possible to get things working using a shim like Bill suggested. Here's my quick draft of what that might look like:

// react-i18n.js
import PropTypes from 'prop-types';
import intl, { withText, IntlProvider, Text, Localizer } from 'preact-i18n';

// patch in contextTypes
let types = { intl: PropTypes.object };
IntlProvider.contextTypes = Localizer.contextTypes = Text.contextTypes = types;

function processProps(props) {
  props.children = props.children==null ? [] : [].concat(props.children)
  return props;
}

function wrapClass(constructor) {
  let { render } = constructor.prototype;
  constructor.prototype.render = function() {
    return render.call(this, processProps(this.props), this.state, this.context);
  };
  return constructor;
}

function wrap(component) {
  if (component.prototype && component.prototype.render) {
    return wrapClass(component);
  }
  return function(props, context) {
    return component.call(this, processProps(props), context);
  };
}

wrap(IntlProvider);
wrap(Text);
wrap(Localizer);

export default intl;
export { withText, IntlProvider, Text, Localizer };
drzraf commented 4 years ago

I still thing it'd be really useful. Use-case: I'm using a preact-i18n based component in WordPress Gutenberg which is based on React. The inability of IntlProvider to work from React is, sadly, the only one that keeps this preact component from working out of the box.

Stack:

TypeError: this is undefined        preact.module.js:1:746
    Preact 2
        m
        IntlProvider
    renderWithHooks react-dom.js:15246
    mountIndeterminateComponent react-dom.js:17480
    beginWork$1 react-dom.js:18624
    callCallback react-dom.js:341
    invokeGuardedCallbackDev react-dom.js:391
    invokeGuardedCallback react-dom.js:448
    beginWork$$1 react-dom.js:23355
    performUnitOfWork react-dom.js:22346
    workLoopSync react-dom.js:22323
    renderRoot react-dom.js:22016
    renderRoot self-hosted:977
    runRootCallback react-dom.js:21692
    runRootCallback self-hosted:977
    flushSyncCallbackQueueImpl react-dom.js:11491
    unstable_runWithPriority react.js:2820
    runWithPriority$2 react-dom.js:11443
    flushSyncCallbackQueueImpl react-dom.js:11487
    flushSyncCallbackQueue react-dom.js:11476
    discreteUpdates$1 react-dom.js:21815
    discreteUpdates react-dom.js:2357
    dispatchDiscreteEvent react-dom.js:6104
    dispatchDiscreteEvent self-hosted:977
orosro commented 3 years ago

@drzraf I know it passed a long time, do you happen to have the integration code between preact and react? we are trying to use a preact component inside a react app (with typescript) but we had to alias PREACT to REACT in webpack. after that we stumbled upon the preact-i18n issue

drzraf commented 3 years ago

I'm sad I had to give up and our project (of integrating a preact component (which use preact-i18n)) within WordPress (Gutenberg, based on react) is stuck.

Unless there is some move from preact-i18n upstream to ensure a smooth compatibility (which would really benefit to all), we will probably have to rewrite our project using react, at some later point.

orosro commented 3 years ago

Understood, We also dropped preact-i18n because of this and probably will look for another library that is compatible with both react and preact. The workaround/patch provided in 2017 doesn't work