React.Children.map递归?

时间:2015-10-02 22:30:35

标签: reactjs

我正在构建一个用于呈现HTML表单的React组件,并且我发现需要递归遍历我的父Form组件的所有子组件,以便仅为特定类型的子组件添加额外的道具。

一个例子(在JSX中):

<Form>
    <p>Personal Information</p>
    <Input name="first_name" />
    <Input name="last_name" />
    <Input name="email" />
    <Label>
        Enter Your Birthday
        <Input name="birthday" type="date" />
    </Label>
</Form>

在这个例子中,我在我的Form组件中使用了React.Children.map,然后在map函数中我正在检查孩子的“type”和孩子的“type.displayName”以确定我的元素m处理(本机HTML元素或ReactElement):

var newChildren = React.Children.map(this.props.children, function(child) {
    if (is.inArray(child.type.displayName, supportedInputTypes)) {
      var extraChildProps = {
        alertColor: this.props.alertColor,
        displayErrors: this.state.displayErrors
      }
      return React.cloneElement(child, extraChildProps);
    } else {
      return child;
    }
  }.bind(this));

我的问题是React.Children.map只是通过this.props.children进行浅层迭代,我希望它还可以检查孩子的孩子等等。我需要只为我的Input组件添加道具,这样才能他们知道何时显示错误,以及应该显示错误消息的颜色等。在上面的示例中,生日输入没有收到必要的道具,因为它包装在Label组件中。

React.Children.map的任何计划都有“递归”模式或任何其他可以完成我正在尝试做的工具吗?

在一天结束时,我想写一个函数来映射每个孩子(甚至是嵌套的孩子),以便对它进行操作(在这种情况下是克隆)。

5 个答案:

答案 0 :(得分:21)

虽然没有融入React,但这当然是可能的:

import React from "react";

function recursiveMap(children, fn) {
  return React.Children.map(children, child => {
    if (!React.isValidElement(child)) {
      return child;
    }

    if (child.props.children) {
      child = React.cloneElement(child, {
        children: recursiveMap(child.props.children, fn)
      });
    }

    return fn(child);
  });
}

答案 1 :(得分:4)

我已经建立了一个小型图书馆来处理儿童结构。你可以在这里查看:

https://github.com/fernandopasik/react-children-utilities

在您的情况下,您可以使用deepMap方法:

import React from 'react';
import Children from 'react-children-utilities';

var newChildren = Children.deepMap(this.props.children, function(child) {
    if (is.inArray(child.type.displayName, supportedInputTypes)) {
      var extraChildProps = {
        alertColor: this.props.alertColor,
        displayErrors: this.state.displayErrors
      }
      return React.cloneElement(child, extraChildProps);
    } else {
      return child;
    }
}.bind(this));

答案 2 :(得分:3)

如果您希望将道具推送到您的组件下的一组子项中,并自动&#34;,您还可以使用context。这允许你'&#34;给&#34;子组件的属性,功能等,通过父母提供getChildContext()contextTypes,并让孩子&#34;请求&#34;他们与{{1}}。

答案 3 :(得分:1)

对此的简短回答是它目前在React 0.14中不可能。正如FakeRainBrigand提到的那样,它很可能是代码味道,因此它应该促使重新评估您的实现。

答案 4 :(得分:1)

这个帖子实际上错过了正确答案:

const mapRecursive = (children, callback) => (
  React.Children.map(
    children,
    child => (
      child.props.children
        ? [callback(child), mapRecursive(child.props.children, callback)]
        : callback(child)
    ),
  )
);