-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
static methods not hoisted by injectIntl
#196
Comments
For the time being you can use |
@shriah I spent some time digging into this, and I'm not sure why the I'm thinking this simply a limitation of CommonJS, since you have to hang everything off the "default" export in CommonJS, people want the main export to be the component and therefore have to hang things off the constructor. With ES6 modules you can export the component as the With ES6 modules one would: export default injectIntl(Component);
export function fetchData() {} |
@ericf The problem with exporting I also feel using HOC should not restrict the functionality of the wrapped component. I am not sure there is a better way to do this without static functions Promise.all(
// Get array of components that will be rendered from the router state.(Not all components)
// The list of components will be different for each request
initialState.router.components
// We need only components with `fetchData` method
.filter(component => component.fetchData)
// Fetching the data!
// `args` is object with required arguments for `fetchData` method
.map(component => component.fetchData({ /* args */ }))
); |
I agree with @shriah. I have the same problem with |
How is Another related reference point is Facebook's Relay project, which has a HOC factory function similar to |
I just want to stress that this matters to me mostly because of server side rendering.
Reference for other projects that do hoist the statics. |
@shriah I will continue to investigate this as time allows because I wanted to understand the root of the issue and code patterns. For now you can apply call |
Thanks @ericf for pointing me in the direction of this discussion from my PR #219. My use case is pretty much exactly the same as @shriah 's; you can actually see the implementation here. The manual hoisting is done e.g. here, here and here... Using (Sidebar: Ultimately, it feels like it'd be better for the community to standardize on a better protocol for HOCs that wouldn't involve wrapping wrappers in wrappers; right now the kerrokantasi-ui project linked above already has two layers of HOC wrapping for each component, namely react-redux and react-intl, and it's already complicating testing.) |
I'm closing this as 'wontfix' for now. |
Static methods should not be touched by any decoration, this is very strange, guys. |
I write a component:
Imagine I have a lot of usages for
And.. My code stops to work. Why? Because From my point of view, any decorator should extend class functionality. Not decrease. |
I have the same issue! |
I don't consider it a bug, but a design choice. Forwarding statics can be brittle and isn't required for React's component rendering protocol. I did research this and found that many of the usages where people want statics forwarding were for Flux related metadata and functions are not part of the component's own encapsulation; i.e. the component itself never accesses these statics, nor does React the framework. It seems that Defining a ES6 class or function for a React component is declarative and statically analyzable. When you start forwarding a class'/component's static members, it becomes a dynamic, runtime operation — similar to a mixin. This feature was removed from the public version of Relay for this reason: facebook/relay#154 I'd prefer the code be explicit, and written directly in the source code rather than having a dynamic operation mutate the class at runtime to create something different than what is visually defined in the source code. I think the Flux related metadata could actually be moved to explicit exports of the module. When using ES6 modules, it's arguably cleaner and and more explicit to create a Controller View with these exports as it separates the component from the Flux system: export default class Foo extends React.Component {}
export const componentConfig = {};
export function initializeAction() {} I like this pattern, especially for the |
But it's an internationalization component. It's not "cut all static members" module. |
Let abstract from React Components. Static methods is not about metadata or similar things.
Adding |
@TheXardas I don't understand your argument, or what you're constructively adding here.
@Strate again, not a decorator. It's literally a function that returns a component. What's a concrete example of defining component statics that don't make more sense to be explicit exports instead? Remember, |
@ericf ok, I think I understood you. |
FWIW Here's a code example of an alternative as a 'workaround', as mentioned above. @injectIntl
@connect( /*...*/ )
export default MyComponent extends Component {
render() { /*...*/ }
}
MyComponent.fetchData = () => { /*...*/ } While I had the same issue, and it would be pleasant for it to magically go away, @ericf's reasoning is sound--runtime mutation of the class is seems more brittle. Since |
@quicksnap can you please also provide an ES5 version of the 'workaround' ? |
|
for you flow fans: import * as React from 'react';
import {injectIntl as baseInjectIntl, type IntlShape} from 'react-intl';
import hoistNonReactStatic from 'hoist-non-react-statics';
type TOpts = {intlPropName: string, withRef: boolean};
export default function injectIntl<Props, SanitizedProps: $Diff<Props, {intl: IntlShape}>>(
BaseComponent: React.ComponentType<Props>,
options?: TOpts
): React.ComponentType<SanitizedProps> {
const WrappedComponent = baseInjectIntl(BaseComponent, options);
hoistNonReactStatic(WrappedComponent, BaseComponent);
return WrappedComponent;
}
export type {IntlShape} from 'react-intl'; I re-export the |
When I tried using
injectIntl
I was not able to access the static method of the child component. Theconnect
component of react-redux is using hoist-non-react-statics for the same purpose. May be doing the same withinjectIntl
will be helpfulThe text was updated successfully, but these errors were encountered: