- 
                Notifications
    You must be signed in to change notification settings 
- Fork 49.7k
Fixes children when using dangerouslySetInnerHtml in a selected <option> #13078
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
Conversation
This fixes an inadvertent cast of undefined children to an empty string when creating an option tag that will be selected:
```
  <select defaultValue="test">
    <option value='test' dangerouslySetInnerHTML={{ __html: '‏ test'}} />
  </select>
```
This causes an invariant error because both children and dangerouslySetInnerHTML are set.
    | Do you mind adding a test to one of  | 
| const optionChildren = flattenOptionChildren(props.children); | ||
| const optionChildren = Array.isArray(props.children) | ||
| ? flattenOptionChildren(props.children) | ||
| : props.children; | 
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.
Checking for an Array isn't sufficient since React supports using iterables as children. Instead, can we invert the logic so that it checks for undefined?
const optionChildren = props.children === undefined
    ? props.children
    : flattenOptionChildren(props.children)Alternatively we could just add that check to flattenOptionChildren directly
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.
You're totally right. I'm not sure all of the possible cases here. I do know that null is also possible in this case. Would null and undefined checks be sufficient?
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 children was null then the user must have explicitly rendered with null as a child. In that case we still want to throw because that counts as using children. We just want to handle the case where there are no children at all, so just checking undefined is sufficient.
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.
In that case we still want to throw because that counts as using children
Do we? On the client we only fire the invariant with == null check so neither null nor undefined counts:
react/src/renderers/dom/shared/ReactDOMComponent.js
Lines 161 to 164 in 571a920
| invariant( | |
| props.children == null, | |
| 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.', | |
| ); | 
Server logic should be the same, shouldn't it? Or am I missing something?
We should have a test for this too I guess.
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 thought we threw for null. You're right, server logic should be the same.
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.
Let's make sure we don't throw for null, and modify the integration test to include this scenario
| Updated to check for  | 
| I'd prefer copy pasting since there's already too much indirection in that file. | 
| Also, can you make a single test with multiple options, each option having a different falsy value (e.g.  | 
| Yes, for some reason I thought that the option had to be selected, but if any of them are selected they are all run through this code path. So I will combine the tests into one. We would expect  | 
| Yeah, a separate test for error consistency would be good. (I think we have a few tests in that suite that show how to assert failures.) | 
| Looks like  | 
| Thank you! | 
This fixes an inadvertent cast of undefined children to an empty string when creating an option tag that will be selected:
This causes an invariant error because both children and dangerouslySetInnerHTML are set.
What is the current behavior?
What is the expected behavior?
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
16.4.1 using node 8. This worked in 15.x.