Change:
When returns instead of accidentally, Fiber does not catch this.
Looks like a bug. Why does it happen?
It looks like does behind the flag, but with the latest alpha release, those paths aren't hit since it's . . edit: that check is actually fine, I still forget how invariant works sometimes It does also but it will actually crash if you try to return , which seems like another issue. Try changing to in the example above and it will crash the tab.
Warning, the link below will cause an infinite loop and might crash the tab/browser __ showing that returning will cause an infinite loop. And showing the endless barrage of errors: I can open a separate issue for this if you'd like
The infinite loop is probably or
Got it, thanks. As for the function issue, I think this would be fixed if those invariant checks in were moved out of a block, or to the correct code path if this warning should be done elsewhere now.
Right now we treat unknown types as empty. We have a special case for since it's almost always a bug (early return). I don't think we decided what we'll do for other unsupported values. We can either warn and treat as empty, or throw.
One disadvantage to throwing versus warning is that it requires an extra check in production, for null. EDIT: I guess we
I think using just a warning would make it too easy for components to silently fail. Existing behavior is to throw as well. is already in the bundle, it's just dead code right now. Can we safely move it outside of the check?
I was actually about to ask if we could make this type of render work? I have various components (Foo, Goo, Hoo, etc.) that I need to conditionally render. Right now I use : if would work, instead I could use the map method on the components array:
You can just wrap it in for the same effect.
I made a list of different things which I think we should (dis)allow as return values. It's based on what we did in 15, but with support for numbers/strings/arrays. The ones with asterisk are the ones we currently silently skip (but used to error on). The ones with two asterisks are the ones we always skipped. IMO we should at least warn about them. Need to evaluate how many more conditions this would add. We probably need to start with warnings anyway because we might already happen to rely on some of them at FB since we enabled new features a while ago. I only feel strongly about here because it’s a really common one. For example if you misunderstand components and return rather than .
Since seems harmless, and seems rare, looks like the actionable item here is just to warn on . Whether as a host child (e.g. of a ) or as a return value.

Discussion:
var React; var ReactDOM; var ReactDOMServer; <del> var ReactDOMFeatureFlags; </del> var ReactTestUtils; <ins> var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); </ins> describe('ReactComponent', () => { function normalizeCodeLocInfo(str) { return str && str.replace(/(at .+?:d+)/g, '(at **)');

React = require('react'); ReactDOM = require('react-dom'); ReactDOMServer = require('react-dom/server'); <del> ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); </del> ReactTestUtils = require('react-dom/test-utils'); });

'    in Foo (at **)', ); }); <ins> if (ReactDOMFeatureFlags.useFiber) { describe('with new features', () => { beforeEach(() => { require('ReactFeatureFlags').disableNewFiberFeatures = false; }); it('warns on function as a return value from a function', () => { function Foo() { return Foo; } spyOn(console, 'error'); var container = document.createElement('div'); ReactDOM.render(<Foo />, container); expectDev(console.error.calls.count()).toBe(1); expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( 'Warning: Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of <Component /> from render. ' + 'Or maybe you meant to call this function rather than return it.n' + '    in Foo (at **)', ); }); it('warns on function as a return value from a class', () => { class Foo extends React.Component { render() { return Foo; } } spyOn(console, 'error'); var container = document.createElement('div'); ReactDOM.render(<Foo />, container); expectDev(console.error.calls.count()).toBe(1); expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( 'Warning: Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of <Component /> from render. ' + 'Or maybe you meant to call this function rather than return it.n' + '    in Foo (at **)', ); }); it('warns on function as a child to host component', () => { function Foo() { return <div><span>{Foo}</span></div>; } spyOn(console, 'error'); var container = document.createElement('div'); ReactDOM.render(<Foo />, container); expectDev(console.error.calls.count()).toBe(1); expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( 'Warning: Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of <Component /> from render. ' + 'Or maybe you meant to call this function rather than return it.n' + '    in span (at **)n' + '    in div (at **)n' + '    in Foo (at **)', ); }); it('does not warn for function-as-a-child that gets resolved', () => { function Bar(props) { return props.children(); } function Foo() { return <Bar>{() => 'Hello'}</Bar>; } spyOn(console, 'error'); var container = document.createElement('div'); ReactDOM.render(<Foo />, container); expect(container.innerHTML).toBe('Hello'); expectDev(console.error.calls.count()).toBe(0); }); }); } </ins> });

} } <ins> function warnOnFunctionType() { warning( false, 'Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of <Component /> from render. ' + 'Or maybe you meant to call this function rather than return it.%s', getCurrentFiberStackAddendum() || '', ); } </ins> // This wrapper function exists because I expect to clone the code in each path // to be able to optimize each path individually by branching early. This needs // a compiler or we can do it manually. Helpers that don't need this branching

throwOnInvalidObjectType(returnFiber, newChild); } <ins> if (__DEV__) { const disableNewFiberFeatures = ReactFeatureFlags.disableNewFiberFeatures; if (!disableNewFiberFeatures && typeof newChild === 'function') { warnOnFunctionType(); } } </ins> return null; }

throwOnInvalidObjectType(returnFiber, newChild); } <ins> if (__DEV__) { if (!disableNewFiberFeatures && typeof newChild === 'function') { warnOnFunctionType(); } } </ins> if (!disableNewFiberFeatures && typeof newChild === 'undefined') { // If the new child is undefined, and the return fiber is a composite // component, throw an error. If Fiber return types are disabled,