使用可迭代对象作为 React 组件

源码

最近看 React 源码的时候发现其在处理数组的同时也对可迭代协议做了处理,因此 React 组件可以是一个返回可迭代对象的函数。源码如下:

reconcileChildFibersImpl

if (isArray(newChild)) {
  return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, lanes, mergeDebugInfo(debugInfo, newChild._debugInfo));
}
if (getIteratorFn(newChild)) {
  return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, lanes, mergeDebugInfo(debugInfo, newChild._debugInfo));
}

getIteratorFn

  var MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
  var FAUX_ITERATOR_SYMBOL = '@@iterator';
  function getIteratorFn(maybeIterable) {
    if (maybeIterable === null || typeof maybeIterable !== 'object') {
      return null;
    }
    var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];

    if (typeof maybeIterator === 'function') {
      return maybeIterator;
    }

    return null;
  }

可以看到 React 会判断 newChild 是否可迭代——通过 Symbol.iterator@@iterator 属性。

现在我们可以构造一个这样的组件了:

function IteratorComponent() {
  return {
    [Symbol.iterator]() {
      return {
        n: 0,
        next() {
          const tag = "h" + ++this.n;
          return {
            value: React.createElement(tag, {
              key: tag
            }, this.n),
            done: this.n > 4,
          };
        },
      };
    },
  };
}

上述组件最终会渲染出 4 个 h{n} 标签。

注意事项

  1. React 虽然支持可迭代协议,但是并不支持 generator
  2. 因为 React 会多次渲染或者会校验迭代器值的情况,对象中的 Symbol.iterator 函数必须是纯函数,即每次调用都是返回一个新的迭代器。

参考

  1. 迭代协议
posted @ 2024-03-27 21:59  雷夫·麦  阅读(3)  评论(0编辑  收藏  举报