React将props传递给子组件时覆盖父组件的父级props

3
我将用一个例子来解释我所寻找的功能。
 const Grandparent = React.createClass({
    render: function(){
        return (<div>
                    <Parent>
                        <button className={this.props.parentClassName} />
                    </Parent>
                <div>
                    )
    }
});

const Parent = React.createClass({
        render: function(){
            const childrenWithProps = React.Children.map(this.props.children, (child) => {
                return React.cloneElement(child, {parentClassName: 'Murphy'});
            });
            return (<div>
                {childrenWithProps}
            </div>)
        }
    });

我希望的是父组件能够拦截GrandParent中设置的props.parentClassName并进行更改,如果它不存在就创建它。
为了使按钮接收到正确的parentClassName,我必须创建一个自定义的Button组件,只从父组件接收props,像这样:
React.createClass({
    render: function(){
        return (<button className={this.props.parentClassName} />)
    }
});

我希望如果可能的话,避免这种情况发生,因为这会剥离掉我想在声明初始组件时可见的代码。
所以,我想要这样:
 React.createClass({
        render: function(){
            return (<div>
                        <Parent>
                            <button className={
//From Parent Component and not the GrandParent Component
this.props.parentClassName

} />
                        </Parent>
                    <div>
                        )
        }
    });

不要这样做

 React.createClass({
        render: function(){
            return (<div>
                        <Parent>
                            <Button />
                        </Parent>
                    <div>
                        )
        }
    });

const Button = React.createClass({
        render: function(){
            return (<button className={this.props.parentClassName} />)
        }
    });

props.parentClassName 是从 <Parent> 组件中返回的,而不是从 <GrandParent> 组件中返回的。


2
我仍然不确定您要解决什么问题?或者您希望React如何工作与当前有何不同? - rossipedia
我为了更清晰而编辑了这篇文章。 - DrivingInsanee
你能否创建带有名称和defaultProps的组件(例如“var Foo = React.createClass({defaultProps: ...}))”? - vbarbarosh
@vbarbarosh 那会怎么帮助呢?我不明白。 - DrivingInsanee
1
我不理解这个问题的原因有几个:1)“Parent”组件在哪里?2)“parentClassName”应该从哪里来?3)你实际上想要实现什么? - vbarbarosh
好的,我又编辑了一下。希望这次清楚了。 - DrivingInsanee
2个回答

2

认为我理解你想做什么。我确定这不是你要找的答案,但 React 并不是那样设计的。你可以(虽然你真的不应该这样做,但你可以)使用 flux 容器,在 flux 存储中保存父元素的 className,并在上面显示的类中调用它。

我建议重新考虑如何以 React 的方式来完成这个任务,而不是使用 Flux 或尝试制作 hacky 解决方案。

根据我的经验,当渲染像这样的自定义组件时:

return (
  <customComponent>
    <button />
  </customComponent>
);

在编程中,最好将<button />作为属性包含在内:

return (
  <customComponent buttonElement={<button />} />
);

并在customComponent类的渲染函数中呈现{this.props.buttonElement},并将其放置在所需位置。如果您不打算向customComponent的每个实例传递按钮,则可以在customComponent的渲染函数中执行此操作:

if(typeof(this.props.buttonElement) !== "undefined") {
  var buttonElement = this.props.buttonElement;
}
else {
  var buttonElement = "";
}
render (
  {buttonElement}
);

1

我希望父组件能够拦截GrandParent中设置的props.parentClassName并更改它,或者在其不存在时创建它。

一个组件不能拦截来自其父组件的props,因为它只能访问其子组件!

我仍然不清楚您想要实现什么...以下代码是否符合您的要求?

import _ from 'underscore';
import React from 'react';

class Grandparent extends React.Component
{
    render() {
        return (
            <div {... this.props}>
                <Parent>
                    <span>hello</span>
                    <span>welcome</span>
                    <span className="red">red</span>
                </Parent>
            </div>
        );
    }
}

// Parent component will add ``className="border"`` to each its
// child without ``className`` property.
class Parent extends React.Component
{
    render() {
        return (
            <div {... this.props}>
                {_.map(this.props.children, (v, k) =>
                    React.cloneElement(v, {className: v.props.className || 'border', key: k}))}
            </div>
        );
    }
}

不幸的是,这不是我要找的。也许“intercept”这个词不对,但我想做的是用父组件设置子组件而不是祖先组件。 - DrivingInsanee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接