用react.js遇到的最大问题求解:不可避免地需要修改this.props.children的样式

#1

疑问如题。举一个简单的例子:

<MyParentComponent gap={3}>
  <MyChildA/>
  <MyChildA/>
  <MyChildB/>
  <MyChildB/>
</MyParentComponent>

上面结构中,通过MyParentComponent中的gap属性来决定它的子组件之间的margin为3像素,也就是说,在MyParentComponent的定义中,需要对this.props.children的style进行修饰。

目前我的解决办法是遍历this.props.children,同时通过React.cloneElement(child, {style: someNewStyle})来克隆出修饰过样式之后的“子组件复制品”(因为this.props.children中的子组件不可修改)。

然而这样复制出额外组件的方法显然不是最优的,而且也繁琐,难以理解。

因此发来社区求助。如果上面的描述有不详细之处,请随时提出以便我及时补充。

#2

直接把gap传给MyChildX不行吗?

#3

意思是直接把gap = {x}写在MyChildX元素上?
问题是gap这个属性应该是MyParentComponent这个组件的特质,当我编写MyParentComponent组件时,我并不知道未来它会包含哪些子组件,也许会有MyChildA,MyChildB,也许会有MyChildC……
换句话说,当我编写MyParentComponent组件的时候,我只想要它的直系子组件之间的margin为一个可写的固定值,而不管它会容纳什么子组件。

#4

501错误

#5

貌似需求也不多见,可不可以挂载时生成一段 css,用子元素选择器来实现

#6

你这个需求的化其实用css更合适,直接强制使用子元素选择器设置子组件的margin.
如果非要从React层面走的化
要么利用Mixin所有的子组件都集成这个Mixin,这样的化每个组件都会包含gap这个属性.
要么就是你说的这种克隆的方法,直接修改样式或者再加一层通用方便的容器节点.
但是都没有直接修改css来的方便

#7

感谢lpy和simongfxu朋友的回答。
我突然想到为什么忽略了css,因为是在react-native项目中遇到这个问题,rn没有css。当然react.js同理,只不过可以通过css样式绕过这个问题。
无论如何,我觉得react官方把this.props.children强制设置为不可写是不合理的,导致我们开发者有时需要舍近求远寻找解决方案。不知道各位对此怎么看,或者在这个问题上是不是有更好的解决办法……

#8

这个问题我也遇到过,我曾经尝试了两种方式来规避,

一种肯定是CSS,这个没话说,不说多优美,反正能解决

第二种不确定是好是坏,像这样需要修改子组件样式的父级组件,我给新建了一个统一的子组件容器,
例如,A 下可能会有许多个 B,这时候,我用一个固定的 C(例如叫A.Item之类的) 包裹住单个 B,这样,我要设置props的时候,只需要针对这个统一的 B 进行修改,不必关心是否每个 children 有没有处理相关的 props

像这样:

A: render() {
    return <div>
        {this.props.children.map(function(child) {
            return <A.Box style={...xxxxStyle}>child</A.Box>;
        })}
    </div>;
}

其实,官方的意思和我平时做的东西来看,一个组件里的子组件,大多是可以再抽一个子组件的,无法再抽并且直接使用 this.props.children 的时候,往往是已经没有共性的内容了。。

#9

谢谢darkty2009的回答。
加一个包裹组件确实是react.js下可行的方案,而且可能是目前能找到最好的方案,唯一缺点在于多了一层额外的DOM元素。
其实是不是这个A.Box也可以直接用div。
另外在flex布局的react-native项目里,因为flex布局的关系,这个方案似乎不可行。

#10

子组件多的话这方法不错。如果只有一个子组件,更多的是用clone方法,如果这里传递的属性是一个函数,比如说是一个事件处理函数,子组件接收这个函数来做处理

#11

我其实想 可以使用在每个子组件上加一个ref~ 然后再循环ref

#12

可以试试这个 pattern:https://medium.com/@iammerrick/function-as-child-components-5f3920a9ace9

#13

还有一招,使用React的context特性(React Context Guide),间接传递属性给容器组件的子组件