Skip to content

Commit

Permalink
Warn when using one-shot iterators as children
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Apr 29, 2022
1 parent ce13860 commit f26d8ed
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/react-dom/src/__tests__/ReactMultiChild-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,29 @@ describe('ReactMultiChild', () => {
ReactDOM.render(<Foo />, div);
});

it('should warn when using one-shot iterators as children', () => {
function Foo() {
const iterator = [<h1 key="1">Hello</h1>, <h1 key="2">Dave</h1>].values();

return iterator;
}

const div = document.createElement('div');
expect(() => {
ReactDOM.render(<Foo />, div);
}).toErrorDev(
'Using a TOOD-understandable-term as children is unsupported and will likely yield ' +
'unexpected results because enumerating a TOOD-understandable-term mutates it. ' +
'You may convert it to an array with `Array.from()` or the ' +
'`[...spread]` operator before rendering. Keep in mind ' +
'you might need to polyfill these features for older browsers.\n' +
' in Foo (at **)',
);

// Test de-duplication
ReactDOM.render(<Foo />, div);
});

it('should not warn for using generators in legacy iterables', () => {
const fooIterable = {
'@@iterator': function*() {
Expand Down
17 changes: 17 additions & 0 deletions packages/react-reconciler/src/ReactChildFiber.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {pushTreeFork} from './ReactFiberTreeContext.new';

let didWarnAboutMaps;
let didWarnAboutGenerators;
let didWarnAboutOneShotIterators;
let didWarnAboutStringRefs;
let ownerHasKeyUseWarning;
let ownerHasFunctionTypeWarning;
Expand Down Expand Up @@ -949,6 +950,22 @@ function ChildReconciler(shouldTrackSideEffects) {
didWarnAboutMaps = true;
}

// Warn about using one-shot iterators as children
const isOneShotIterator =
iteratorFn.call(newChildrenIterable) === newChildrenIterable;
if (isOneShotIterator) {
if (!didWarnAboutOneShotIterators) {
console.error(
'Using a TOOD-understandable-term as children is unsupported and will likely yield ' +
'unexpected results because enumerating a TOOD-understandable-term mutates it. ' +
'You may convert it to an array with `Array.from()` or the ' +
'`[...spread]` operator before rendering. Keep in mind ' +
'you might need to polyfill these features for older browsers.',
);
}
didWarnAboutOneShotIterators = true;
}

// First, validate keys.
// We'll get a different iterator later for the main pass.
const newChildren = iteratorFn.call(newChildrenIterable);
Expand Down
17 changes: 17 additions & 0 deletions packages/react-reconciler/src/ReactChildFiber.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {pushTreeFork} from './ReactFiberTreeContext.old';

let didWarnAboutMaps;
let didWarnAboutGenerators;
let didWarnAboutOneShotIterators;
let didWarnAboutStringRefs;
let ownerHasKeyUseWarning;
let ownerHasFunctionTypeWarning;
Expand Down Expand Up @@ -949,6 +950,22 @@ function ChildReconciler(shouldTrackSideEffects) {
didWarnAboutMaps = true;
}

// Warn about using one-shot iterators as children
const isOneShotIterator =
iteratorFn.call(newChildrenIterable) === newChildrenIterable;
if (isOneShotIterator) {
if (!didWarnAboutOneShotIterators) {
console.error(
'Using a TOOD-understandable-term as children is unsupported and will likely yield ' +
'unexpected results because enumerating a TOOD-understandable-term mutates it. ' +
'You may convert it to an array with `Array.from()` or the ' +
'`[...spread]` operator before rendering. Keep in mind ' +
'you might need to polyfill these features for older browsers.',
);
}
didWarnAboutOneShotIterators = true;
}

// First, validate keys.
// We'll get a different iterator later for the main pass.
const newChildren = iteratorFn.call(newChildrenIterable);
Expand Down

0 comments on commit f26d8ed

Please sign in to comment.