Skip to content
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: React DOM crashes when <option> contains three interpolated valu… #12078

Closed
wants to merge 3 commits into from

Conversation

stephenkingsley
Copy link

fix #11911
…e if one is a conditional. #11911

Before submitting a pull request, please make sure the following is done:

  1. Fork the repository and create your branch from master.
  2. Run yarn in the repository root.
  3. If you've fixed a bug or added code that should be tested, add tests!
  4. Ensure the test suite passes (yarn test). Tip: yarn test --watch TestName is helpful in development.
  5. Run yarn test-prod to test in the production environment. It supports the same options as yarn test.
  6. If you need a debugger, run yarn debug-test --watch TestName, open chrome://inspect, and press "Inspect".
  7. Format your code with prettier (yarn prettier).
  8. Make sure your code lints (yarn lint). Tip: yarn linc to only check changed files.
  9. Run the Flow typechecks (yarn flow).
  10. If you haven't already, complete the CLA.

Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html

@facebook-github-bot
Copy link

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed.

If you have received this in error or have any questions, please contact us at cla@fb.com. Thanks!

@@ -46,7 +46,7 @@ describe('ReactDOMOption', () => {
' in div (at **)\n' +
' in option (at **)',
);
expect(node.innerHTML).toBe('1 2');
expect(node.innerHTML).toBe('1 <div></div> 2');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a behavior change. I don't think we want this.

Copy link
Collaborator

@gaearon gaearon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please:

  1. Don't change the existing behavior (apart from from fixing a bug). It should match how this worked in React 15.

  2. Add a test that would have failed without your fix.

@stephenkingsley
Copy link
Author

Sorry that is my fault! I will fix it in today.

reduce option child
@stephenkingsley
Copy link
Author

@gaearon please review again

@stephenkingsley
Copy link
Author

@gaearon Would you have anytime to review, please?

@gaearon
Copy link
Collaborator

gaearon commented Jan 29, 2018

Can you explain what this is doing? It’s not obvious from the code that it is correct. Generally when submitting a PR it is a good idea to explain how you arrived at this conclusion, when it got broken, whether you can point to React 15 code doing a similar thing, etc.

@stephenkingsley
Copy link
Author

My english is not good enough to explain how I do this.

When render <option>{1}<div />{2}</option>, Option has three children like [textNode, Div, textNode], so I use reduceOptionChild function to remove Div. Because the Div is illegal in option.

If render like this, when change the value, option has one child that is textNode. So react was crash and warning Node was not found. I find out function assertValidProps change this option's child. Before change, this option has three childNodes. When run assertValidProps, the option has one childNode: textNode. So I use span contain textNodes.

<option key={value} value={value}>
  {isSelected && '(Y) '}
  {value} 
  {'Some string'}
</option>

I think you're right, I should do something like React 15 code.

@gaearon
Copy link
Collaborator

gaearon commented Jan 29, 2018

My point is:

  • If this is a regression from React 15 behavior, please implement whatever React 15 did.
  • If this has always been present then let's discuss possible solutions separately.

@aweary
Copy link
Contributor

aweary commented Jan 29, 2018

I only looked at this briefly, but I think there may be a deeper issue with child reconciliation. Specifically this logic (or maybe somewhere else upstream) in commitPlacement

const before = getHostSibling(finishedWork);
// We only have the top Fiber that was inserted but we need recurse down its
// children to find all the terminal nodes.
let node: Fiber = finishedWork;
while (true) {
if (node.tag === HostComponent || node.tag === HostText) {
if (before) {
if (isContainer) {
insertInContainerBefore(parent, node.stateNode, before);
} else {
insertBefore(parent, node.stateNode, before);
}
} else {
if (isContainer) {
appendChildToContainer(parent, node.stateNode);
} else {
appendChild(parent, node.stateNode);
}
}

before should always be a child of parent, and in this case it isn't. I'm not exactly sure why that's the case yet, but my gut feeling is that this solution is fixing a symptom not the problem.

@gaearon
Copy link
Collaborator

gaearon commented Aug 1, 2018

This was fixed in #13261. Thanks!

@gaearon gaearon closed this Aug 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

React DOM crashes when <option> contains three interpolated value if one is a conditional.
4 participants