Skip to content

Commit

Permalink
#1211 - Deprecate withRef in favor of forwardRef and React.forwardRef (
Browse files Browse the repository at this point in the history
…#1271)

* Deprecate withRef in favor of forwardRef and React.forwardRef

Deprecate withRef and use forwardRef prop instead.
When forwardRef is true, the ref passed to the injected component
will be passed down to the wrapped component.

Display a invariant message when withRef is used.

Closes #1211.

* Refactor withIntl to be composable

Refactor the call to withIntl to allow for HoC composing, such as:

export default compose(
  connect(...conntextOptions),
  withIntl(intlOptions)
)

This is done without changing the main API, options can still be passed
in as second arguments to withIntl too.

Add 'react-is' as a strict dependency, change the rollup config to be
able to properly build with it.
  • Loading branch information
mrijke authored and redonkulus committed May 27, 2019
1 parent ee7888c commit 6c36e74
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 146 deletions.
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -72,7 +72,8 @@
"intl-messageformat": "^2.1.0",
"intl-relativeformat": "^2.1.0",
"invariant": "^2.1.1",
"react-display-name": "^0.2.4"
"react-display-name": "^0.2.4",
"react-is": "^16.3.1"
},
"peerDependencies": {
"prop-types": "^15.5.4",
Expand Down
1 change: 1 addition & 0 deletions rollup.config.dist.js
Expand Up @@ -41,6 +41,7 @@ export default {
}),
commonjs({
sourcemap: true,
namedExports: {'react-is': ['isValidElementType']},
}),
replace({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.lib.js
Expand Up @@ -27,7 +27,7 @@ export default {
],
plugins: [
babel(),
commonjs(),
commonjs({namedExports: {'react-is': ['isValidElementType']}}),
nodeResolve({
jsnext: true
})
Expand Down
72 changes: 41 additions & 31 deletions src/components/withIntl.js
@@ -1,4 +1,5 @@
import React, {Component, createContext} from 'react';
import {isValidElementType} from 'react-is';
import hoistNonReactStatics from 'hoist-non-react-statics';
import invariant from 'invariant';
import {invariantIntlContext} from '../utils';
Expand All @@ -8,62 +9,71 @@ function getDisplayName(Component) {
}

const IntlContext = createContext(null);
const {
Consumer: IntlConsumer,
Provider: IntlProvider
} = IntlContext
const {Consumer: IntlConsumer, Provider: IntlProvider} = IntlContext;

export const Provider = IntlProvider
export const Context = IntlContext
export const Provider = IntlProvider;
export const Context = IntlContext;

export default function withIntl(WrappedComponent, options = {}) {
export default function withIntl(componentOrOptions, options) {
if (isValidElementType(componentOrOptions)) {
// use call to make `options` available on `this`
return createWrapper.call({options}, componentOrOptions);
}
// return a function with `options` bound to `this`
return createWrapper.bind({options: componentOrOptions});
}

function createWrapper(WrappedComponent) {
let options = (this && this.options) || {};
const {
intlPropName = 'intl',
forwardRef = false,
// DEPRECATED - use forwardRef and ref on injected component
withRef = false,
enforceContext = true
enforceContext = true,
} = options;

class withIntl extends Component {
invariant(
!withRef,
'[React Intl] withRef and getWrappedInstance() are deprecated, ' +
"instead use the 'forwardRef' option and create a ref directly on the wrapped component."
);

class WithIntl extends Component {
static displayName = `withIntl(${getDisplayName(WrappedComponent)})`;
static WrappedComponent = WrappedComponent;

wrappedInstance = (ref) => {
this.wrappedInstance.current = ref;
}

getWrappedInstance() {
invariant(
withRef,
'[React Intl] To access the wrapped instance, ' +
'the `{withRef: true}` option must be set when calling: ' +
'`withIntl()`'
);

return this.wrappedInstance.current;
}

render () {
render() {
return (
<IntlConsumer>
{(intl) => {
{intl => {
if (enforceContext) {
invariantIntlContext({ intl });
invariantIntlContext({intl});
}

return (
<WrappedComponent
{...{
...this.props,
[intlPropName]: intl
[intlPropName]: intl,
}}
ref={withRef ? this.wrappedInstance : null}
ref={forwardRef ? this.props.forwardedRef : null}
/>
);
}}
</IntlConsumer>
)
);
}
}

return hoistNonReactStatics(withIntl, WrappedComponent);
if (forwardRef) {
return hoistNonReactStatics(
React.forwardRef((props, ref) => (
<WithIntl {...props} forwardedRef={ref} />
)),
WrappedComponent
);
}

return hoistNonReactStatics(WithIntl, WrappedComponent);
}

0 comments on commit 6c36e74

Please sign in to comment.