Repository: facebook/react
File: packages/react-reconciler/src/ReactChildFiber.js (JavaScript)

Code before:
        for (let i = 0; i < children.length; i++) {
          if (!validateSuspenseListNestedChild(children[i], i)) {
            return;
          }
        }
      } else {
        const iteratorFn = getIteratorFn(children);
        if (typeof iteratorFn === 'function') {
          const childrenIterator = iteratorFn.call(children);
          if (childrenIterator) {
            let step = childrenIterator.next();
            let i = 0;
            for (; !step.done; step = childrenIterator.next()) {
              if (!validateSuspenseListNestedChild(step.value, i)) {
                return;
              }
              i++;
            }
          }
        } else if (
          enableAsyncIterableChildren &&
          typeof (children: any)[ASYNC_ITERATOR] === 'function'
        ) {
          // TODO: Technically we should warn for nested arrays inside the
          // async iterable but it would require unwrapping the array.
          // However, this mistake is not as easy to make so it's ok not to warn.
        } else {
          console.error(
            'A single row was passed to a <SuspenseList revealOrder="%s" />. ' +
              'This is not useful since it needs multiple rows. ' +
              'Did you mean to pass multiple children or an array?',
            revealOrder,
          );
        }
      }
    }
  }
}


Review comment (suggestion):
It can be costly to iterate this twice so we avoid it.

Ideally, we'd probably move the `validateSuspenseListChildren` warning to be integrated with the rest ChildFiber instead so that it can be done in a single pass. Even for sync iterators.

Code after:
        for (let i = 0; i < children.length; i++) {
          if (!validateSuspenseListNestedChild(children[i], i)) {
            return;
          }
        }
      } else {
        const iteratorFn = getIteratorFn(children);
        if (typeof iteratorFn === 'function') {
          const childrenIterator = iteratorFn.call(children);
          if (childrenIterator) {
            let step = childrenIterator.next();
            let i = 0;
            for (; !step.done; step = childrenIterator.next()) {
              if (!validateSuspenseListNestedChild(step.value, i)) {
                return;
              }
              i++;
            }
          }
        } else if (
          enableAsyncIterableChildren &&
          typeof (children: any)[ASYNC_ITERATOR] === 'function'
        ) {
          // TODO: Technically we should warn for nested arrays inside the
          // async iterable but it would require unwrapping the array.
          // However, this mistake is not as easy to make so it's ok not to warn.
        } else if (
          enableAsyncIterableChildren &&
          children.$$typeof === REACT_ELEMENT_TYPE &&
          typeof children.type === 'function' &&
          // $FlowFixMe
          (Object.prototype.toString.call(children.type) ===
            '[object GeneratorFunction]' ||
            // $FlowFixMe
            Object.prototype.toString.call(children.type) ===
              '[object AsyncGeneratorFunction]')
        ) {
          console.error(
            'A generator Component was passed to a <SuspenseList revealOrder="%s" />. ' +
              'This is not supported as a way to generate lists. Instead, pass an ' +
              'iterable as the children.',
            revealOrder,
          );
        } else {
          console.error(
            'A single row was passed to a <SuspenseList revealOrder="%s" />. ' +
              'This is not useful since it needs multiple rows. ' +
              'Did you mean to pass multiple children or an array?',
            revealOrder,
          );
        }