-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Fix bug introduced in #677 #680
Conversation
@@ -47,6 +47,9 @@ export function instEqual(a, b, lenComp) { | |||
|
|||
export function instHasClassName(inst, className) { | |||
const node = findDOMNode(inst); | |||
if (!node) { // inst renders null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it better to check !node
or node === null
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the instance renders "nothing", it could return an empty array, or null
, or undefined
… is there perhaps a react method we could use, like React.Children.count
or something, that would cover us here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But can a react component return anything other than null
or a react element? Besides, what we're talking about here is the output of findDOMNode
, can it be anything other than a dom element or null
, I dont know...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point - https://facebook.github.io/react/docs/react-dom.html#finddomnode makes it seem like it's only null
or a node. I wonder if then it would be better to use === null
specifically so that it blows up if React changes the behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I've changed it to === null
same thing as in #679 (comment) applies here I believe, after #677 |
I think the two PRs can coexist - |
@ljharb You wouldn't expect this test to pass? const Foo = () => <div className="bar" />
const wrapper = mount(<Foo />)
expect(wrapper.hasClass('bar')).to.equal(true) |
hmm, that's a good point. no, i wouldn't; that should work. |
So what should we do here, throw if used on a SFC? |
Sorry, my comment was confusing. I would indeed expect that test to pass - so SFCs should work, and not throw. If they won't work properly, then they should throw, of course. |
@ljharb sorry for the late reply, I don't think there's any way to get a ref to the dom node rendered for a stateless component so I'll update the PR to make the method throw when used on a stateless component. |
So, apparently the react documentation is not up-to-date or I misread it because findDOMNode does work on functional components, as such, I've updated the PR with tests for hasClass on SFCs and removed the previously added check on getDOMNode for SFCs. Thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems good, but lets get lots of eyes on it prior to merging
|
||
it('should throw when wrapping an SFC', () => { | ||
it('should return the outer most DOMComponent of the inner div wrapper', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"outermost" is one word :-p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed it is ;) updated
|
||
it('should throw when wrapping multiple elements', () => { | ||
const wrapper = mount(<SFC />).find('span'); | ||
expect(() => wrapper.getDOMNode()).to.throw(Error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we test the error message like we had before? Testing that it throws any error seems brittle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably both would be good; but if we want our error tests to be more robust we should be making error subclasses, not doing string comparisons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error subclasses are a better solution, I'm on board with that approach. But a string comparison would be better than nothing, so I'm fine with doing that for now too.
FYI @ljharb @aweary https://twitter.com/dan_abramov/status/808781309745201152 |
Yes, if it works, we should support it for SFCs. If it breaks in a major version (since it'd be a breaking change), we'll have to conditionally support it based on the react version. |
@ljharb since we're relying on "accidental" non-public behaviour of the ReactDOM API it could theoretically break in a patch version |
Sadly "if it's reachable, it's public" isn't a philosophy React tends to follow, but in this case I think we can, since it would probably cause lots of breakage across the React ecosystem. I think we should be optimistic here that React will follow semver. |
@ljharb I think we might be pretty alone in relying on this particular behaviour of findDOMNode, (especially because the usefulness of using this very convoluted way (it requires rendering the SFC as a child of a class component, ReactWrapperComponent for us, and accessing it from there) of accessing dom nodes for SFCs is next to null outside of testing (but very useful in testing obviously)) |
- passing test for composite component that renders composite component which itself renders a dom element - failing test for composite component that renders null
see https://facebook.github.io/react/docs/react-dom.html#finddomnode for return values of findDOMNode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@ljharb Can we get a patch release to npm with these changes? We're going to have to pin to 2.6.0 as a few of our tests are currently broken due |
Sure, I should be able to get one out today or tomorrow. |
PR #677 introduced a bug where calling
hasClass
on a component that rendersnull
would throw an exception. This fixes that.