-
Notifications
You must be signed in to change notification settings - Fork 26.5k
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
[React] Add guidelines for setting displayName on higher-order components #968
Comments
This seems like a reasonable thing to add to the React guide (although imo HOCs should generally be avoided in favor of composition, when possible) |
Agreed! |
This guideline will help us keep our higher-order components consistent and easy to understand. Fixes #968.
@lencioni - I had a question about this pattern when using https://github.com/airbnb/enzyme (I'm assuming you use enzyme because you're an airbnb member). Normally you can pass the component's name as a string as a selector. Imagine this scenario: const ChildComponent = () => <div />
const ParentComponent = () => <ChildComponent />
describe('ParentComponent', () => {
it('renders ChildComponent (select by class)', function() {
const wrapper = shallow(<ParentComponent />)
expect(wrapper.is(ChildComponent)).to.be.true
})
it('renders ChildComponent (select by class name)', function() {
const wrapper = shallow(<ParentComponent />)
expect(wrapper.is('ChildComponent')).to.be.true
})
}) This all works fine. Now imagine ChildComponent needs some added functionality, you decide to decorate it: function withFoo(WrappedComponent) {
function WithFoo(props) {
// TODO: do something special here.
return <WrappedComponent {...props} />
}
WithFoo.displayName = `withFoo(${WrappedComponent.displayName || WrappedComponent.name})`;
return WithFoo;
}
@withFoo
class ChildComponent extends React.Component {
render () {
<div />
}
}
const ParentComponent = () => <ChildComponent />
describe('ParentComponent', () => {
it('renders ChildComponent (select by class)', function() {
const wrapper = shallow(<ParentComponent />)
expect(wrapper.is(ChildComponent)).to.be.true
})
it('renders ChildComponent (select by class name)', function() {
const wrapper = shallow(<ParentComponent />)
expect(wrapper.is('ChildComponent')).to.be.true
})
}) The second test now fails! It would need to be: it('renders ChildComponent (select by class name)', function() {
const wrapper = shallow(<ParentComponent />)
expect(wrapper.is('withFoo(ChildComponent)')).to.be.true
}) I've been prefixing as this rule describes and in these cases I'll just import the component class and select by that
Nothing earth shattering, but something akin to code smells so I'm wondering how other people handle it. |
Related: airbnb/react-with-styles#32 (comment)
For testing the underlying component with Enzyme, you probably want to use I hope that helps! Let me know if you have any questions. |
Cool, thanks for the response! |
This guideline will help us keep our higher-order components consistent and easy to understand. Fixes airbnb#968.
This guideline will help us keep our higher-order components consistent and easy to understand. Fixes airbnb#968.
Higher-order components are functions that take a Component as an argument and return a new Component that renders the passed-in Component. When doing this, it is nice to set the
displayName
on the generated Component to make it obvious (e.g. in dev tools) to understand what is going on. I prefer the convention ofhigherOrderComponent(WrappedComponent)
.For example, if I have a higher-order component called
withFoo
and a component that is wrapped by this calledBar
:the
displayName
on the generated component would be set towithFoo(Bar)
, e.g.:The text was updated successfully, but these errors were encountered: