当前位置: 首页 > 知识库问答 >
问题:

在react.js中将道具传递给父组件

呼延俊风
2023-03-14
var Child = React.createClass({
  render: function() {
    <a onClick={this.props.onClick}>Click me</a>
  }
});

var Parent = React.createClass({
  onClick: function(event) {
    // event.component.props ?why is this not available?
  },
  render: function() {
    <Child onClick={this.onClick} />
  }
});

也许有一种方法可以将组件绑定到事件?

在使用React一年多后,在Sebastien Lorber的回答的激励下,我得出结论,将子组件作为参数传递给父母中的函数实际上不是React的方式,也不是一个好主意。我换了答案。

共有1个答案

韩良策
2023-03-14

编辑:有关ES6更新的示例,请参见结尾示例。

这个答案简单地处理了直接亲子关系的情况。当parent和child可能有很多中介时,请检查以下答案。

虽然它们仍然工作得很好,但其他答案缺少了一些非常重要的东西。

var Child = React.createClass({
  render: function () {
    return <button onClick={this.props.onClick}>{this.props.text}</button>;
  },
});
var Parent = React.createClass({
  getInitialState: function() {
     return {childText: "Click me! (parent prop)"};
  },
  render: function () {
    return (
      <Child onClick={this.handleChildClick} text={this.state.childText}/>
    );
  },
  handleChildClick: function(event) {
     // You can access the prop you pass to the children 
     // because you already have it! 
     // Here you have it in state but it could also be
     //  in props, coming from another parent.
     alert("The Child button text is: " + this.state.childText);
     // You can also access the target of the click here 
     // if you want to do some magic stuff
     alert("The Child HTML is: " + event.target.outerHTML);
  }
});
var Parent = React.createClass({
  getInitialState: function() {
     return {childrenData: [
         {childText: "Click me 1!", childNumber: 1},
         {childText: "Click me 2!", childNumber: 2}
     ]};
  },
  render: function () {
    var children = this.state.childrenData.map(function(childData,childIndex) {
        return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
    }.bind(this));
    return <div>{children}</div>;
  },

  handleChildClick: function(childData,event) {
     alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
     alert("The Child HTML is: " + event.target.outerHTML);
  }
});

JSFiddle

也可以使用this.handlechildclick.bind(null,childIndex),然后使用this.state.childrendata[childIndex]

注我们使用null上下文绑定,因为否则React会发出与其自动绑定系统相关的警告。使用null表示您不想更改函数上下文。又见。

var Parent = React.createClass({
  handleClick: function(childComponent) {
     // using childComponent.props
     // using childComponent.refs.button
     // or anything else using childComponent
  },
  render: function() {
    <Child onClick={this.handleClick} />
  }
});
<Child ref="theChild" .../>
React.findDOMNode(this.refs.theChild)

对于更高级的情况,您希望访问父级中子级的多个引用,子级可以在回调中直接传递所有dom节点。

组件有一个接口(道具),父组件不应该假设子组件的内部工作,包括它的内部DOM结构或它声明引用的DOM节点。父级使用子级的引用意味着您将这两个组件紧密地耦合在一起。

为了说明这个问题,我将引用关于影子DOM的这句话,它在浏览器中用于呈现滑块、滚动条、视频播放器等东西...:

在回调中传递整个组件是危险的,可能会导致新手开发人员做一些非常奇怪的事情,比如调用childcomponent.setstate(...)childcomponent.forceupdate(),或者在父级中为它分配新的变量,从而使整个应用程序更难推理。

编辑:ES6示例

由于现在许多人都在使用ES6,这里有相同的ES6语法示例

const Child = ({
  onClick, 
  text
}) => (
  <button onClick={onClick}>
    {text}
  </button>
)
class Parent1 extends React.Component {
  handleChildClick(childData,event) {
     alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
     alert("The Child HTML is: " + event.target.outerHTML);
  }
  render() {
    return (
      <div>
        {this.props.childrenData.map(child => (
          <Child
            key={child.childNumber}
            text={child.childText} 
            onClick={e => this.handleChildClick(child,e)}
          />
        ))}
      </div>
    );
  }
}
const Parent2 = ({childrenData}) => (
  <div>
     {childrenData.map(child => (
       <Child
         key={child.childNumber}
         text={child.childText} 
         onClick={e => {
            alert("The Child button data is: " + child.childText + " - " + child.childNumber);
                    alert("The Child HTML is: " + e.target.outerHTML);
         }}
       />
     ))}
  </div>
)

PERF警告(应用于ES5/ES6):如果您正在使用purecomponentshouldcomponentupdate,由于在呈现阶段使用onclick={e=>doSomething()},或者直接绑定,因此默认情况下不会优化上述实现,因为每次父级呈现时都会创建一个新函数。如果这是应用程序中的perf瓶颈,则可以将数据传递给子级,并将其重新注入“稳定”回调(在父类上设置,并绑定到类构造函数中的this)中,以便purecomponent优化能够发挥作用,或者您可以实现自己的shouldcomponentupdate并在props比较检查中忽略回调。

您还可以使用Recompose库,它提供更高阶的组件来实现微调优化:

// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}

// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)

// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)

在这种情况下,您可以使用以下方法优化子组件:

const OptimizedChild = onlyUpdateForKeys(['text'])(Child)
 类似资料:
  • 我使用的是dev-express中的react-grid库,库中有一个表组件,我们可以向它传递单元格组件,在CustomCell中,我使用的是Material UI中的菜单 在上述情况下,菜单工作良好, 但是我想要传递道具到这个组件,我尝试了以下操作 在这种情况下菜单不工作,我想知道是否有一个替代的方法来实现第二种情况。

  • 问题内容: 在组件中,我需要将函数的返回值传递给属性。然后从属性需要被传递到的组件。新来的反应。不确定如何将属性从子级传递到组件。 问题答案: 您可以将函数从父级传递给子级,子级可以使用颜色调用该函数(很多操作都类似于事件处理程序)。在App中收到颜色后,使用.setState()将其分配给状态值,然后将其在render()中获取

  • 问题内容: 我已经在子组件的窗体上创建了。使用jquery ajax方法提交该表单后,我将以json格式检索一些数据。我想将该数据置于父组件的状态。那么,react.js中是否有任何方法可以将值或数据从子组件传递到其父组件? 谢谢.. 问题答案: 在没有某种Flux实现的情况下执行此操作的方法是在父元素上创建一个函数来处理来自子级的响应/数据,并将该函数作为道具传递。然后从孩子那里调用该函数。像这

  • 问题内容: 我需要使用路由器将道具传递到组件。这是我的代码: 如您所见,isAuthenticated我想传递给Login组件的道具。 当我登录道具时, isAuthenticated 道具不存在。我做错了什么?如何正确通过道具?我关注了文档以及其他讨论。据我了解,它应该可以工作。的版本 做出反应路由器 和 反应路由器- DOM 是 4.0.0 问题答案: 像这样传递它: 它应该在“登录组件”中可

  • 我试图传递一个道具给一个子组件在反应,但它不显示在所有的道具,当我控制台日志。甚至关键的也不显示。对此的任何帮助都将不胜感激。

  • 问题内容: 我试图找到定义可以以一般方式使用的组件的正确方法: 当然,可以想象并在父组件和子组件之间进行渲染的逻辑。 对于这个问题,这是一个虚拟的实现: 问题是,每当您用于定义包装器组件时,如何将某些属性传递给其所有子组件? 问题答案: 用新道具克隆Children 您可以使用React.Children遍历子级,然后使用React.cloneElement使用新的道具(浅合并)克隆每个元素,例如