Do you want to request a feature or report a bug?
Bug
What is the current behavior?
I get a confusing error when not using a new line in the children of a Consumer un the new Context API:
https://codesandbox.io/s/13n733xp5j
Error:
Fix:
What is the expected behavior?
Component just getting redered
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
16.3.0-alpha.1 and 16.3.0-alpha.0, Chromium 63, Archilinux. React 16.2 didn't support the new Context Api.
We should show a nicer error message. I don't agree this should just render (it's too ambiguous, technically you have a text node there). But the message should make more sense.
@gaearon I'd like to jump in on this!
@elbaumpj it's all yours!
Would someone mind pointing me in the right direction as to where I might find the relevant logic for this issue? I figured it would be in ReactContext.js, but I'm having trouble figuring out where the actual error message is being generated.
Also, I wonder what the new message should say. Something like "The Consumer component's children must return a React element (JSX)"? To be honest, I'm not exactly sure why Consumer demands a new line for it's children.
@elbaumpj you can find the call site using the stack trace from the error thrown in the codesandbox example posted by @ryepesg. The context consumer's render callback is called here:
We should add an invariant
call before calling render
that checks that render
is actually a function.
To be honest, I'm not exactly sure why Consumer demands a new line for it's children.
It doesn't actually require a newline, it just requires that you only render a single child that is a function. In this case, the space before the function created a text node. So when you do:
<Consumer>{() => "foo"}</Consumer>
children
will just be that function that returns "foo". But if you insert a space:
<Consumer> {() => "foo"}</Consumer>
children
will now be [" ", [Function]]
because the space is meaningful. Trying to call that array of children as a function is what causes it to throw. The newline fixes it because a newline doesn't create a new text node. Does that help?
Also, I wonder what the new message should say. Something like "The Consumer component's children must return a React element (JSX)"?
@gaearon probably has better copy for this, but the gist of it should be something like:
A context consumer was rendered with multiple children, or a child that isn't a function. A context consumer expects a single child that is a function. If you did pass a function, Make sure there is no trailing or leading whitespace around it.
@aweary that's all super helpful--thank you!
Took a crack at this at https://github.com/facebook/react/pull/12267 - hope it's not an issue.
@raunofreiberg
I don't really appreciate that, I had clearly claimed this issue and just hadn't got a chance to make my PR yet.
As it states in the docs:
If you decide to fix an issue, please be sure to check the comment thread in case somebody is already working on a fix. If nobody is working on it at the moment, please leave a comment stating that you intend to work on it so other people don鈥檛 accidentally duplicate your effort.
If somebody claims an issue but doesn鈥檛 follow up for more than two weeks, it鈥檚 fine to take over it but you should still leave a comment.
Oops, sorry I merged without looking who took the issue :-(
I assumed that the submitter saw this thread and wouldn't try to submit a PR outside the process.
I guess it's fixed now, but @raunofreiberg please don't take claimed issues in the future.
Got it. My apologies @elbaumpj.
Most helpful comment
@elbaumpj you can find the call site using the stack trace from the error thrown in the codesandbox example posted by @ryepesg. The context consumer's render callback is called here:
https://github.com/facebook/react/blob/d529d2035e3fe741acdf1f01619326588fcca697/packages/react-reconciler/src/ReactFiberBeginWork.js#L871-L872
We should add an
invariant
call before callingrender
that checks thatrender
is actually a function.It doesn't actually require a newline, it just requires that you only render a single child that is a function. In this case, the space before the function created a text node. So when you do:
children
will just be that function that returns "foo". But if you insert a space:children
will now be[" ", [Function]]
because the space is meaningful. Trying to call that array of children as a function is what causes it to throw. The newline fixes it because a newline doesn't create a new text node. Does that help?@gaearon probably has better copy for this, but the gist of it should be something like: