在 React.js 中将 props 传递给父组件

2023-12-02

难道就没有一个简单的方法可以让孩子过关吗?props在 React.js 中使用事件到其父级?

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} />
  }
});

我知道您可以使用受控组件来传递输入值,但传递整个套件和 kaboodle 会很好。有时,子组件包含一组您不想查找的信息。

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

更新 – 9/1/2015

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


Edit:有关 ES6 更新的示例,请参阅最后的示例。

这个答案只是处理直接亲子关系的情况。当父母和孩子可能有很多中介时,检查这个answer.

其他解决方案没有抓住重点

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

在 React.js 中,是否没有一种简单的方法可以使用事件将子级的 props 传递给其父级?

父母已经有了那个孩子道具!:如果孩子有一个道具,那么这是因为其父母向孩子提供了该道具!为什么你希望孩子将道具传回父母,而父母显然已经拥有该道具?

更好的实施

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);
  }
});

JsFiddle

家长与孩子名单:你仍然拥有父母所需的一切,不需要让孩子变得更复杂。

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]

注意我们绑定的是nullcontext,因为否则 React 会发出与其相关的警告自动绑定系统。使用 null 意味着您不想更改函数上下文。See also.

关于其他答案中的封装和耦合

这对我来说是一个bad耦合和封装方面的想法:

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} />
  }
});

使用道具: 正如我上面所解释的,您已经在父组件中拥有了 props,因此传递整个子组件来访问 props 是没有用的。

使用参考文献: 您已经在事件中获得了点击目标,在大多数情况下这就足够了。 此外,您可以直接在子项上使用 ref :

<Child ref="theChild" .../>

并使用以下命令访问父级中的 DOM 节点

React.findDOMNode(this.refs.theChild)

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

该组件有一个接口(props),并且父组件不应该假设子组件的内部工作的任何内容,包括其内部 DOM 结构或它声明的 refs 的 DOM 节点。父级使用子级的引用意味着您将这两个组件紧密耦合。

为了说明这个问题,我将引用以下内容影子 DOM,在浏览器内部用于渲染滑块、滚动条、视频播放器等内容......:

他们在 Web 开发人员可以达到的范围之间建立了界限 以及什么被认为是实现细节,因此无法访问 你。然而,浏览器可以随意跨越这个边界。 有了这个边界,他们就能够构建所有 HTML 元素 使用同样古老的 Web 技术,摆脱 div 和 span 就像你会的那样。

问题是,如果您让子级实现细节泄漏到父级中,则很难在不影响父级的情况下重构子级。这意味着作为库作者(或作为带有 Shadow DOM 的浏览器编辑器),这是非常危险的,因为你让客户端访问太多,使得在不破坏向后兼容性的情况下升级代码变得非常困难。

如果 Chrome 实现了滚动条,让客户端访问该滚动条的内部 dom 节点,这意味着客户端可能会简单地破坏该滚动条,并且当​​ Chrome 在重构后执行自动更新时,应用程序会更容易破坏。滚动条...相反,它们只允许访问一些安全的内容,例如使用 CSS 自定义滚动条的某些部分。

关于使用其他东西

在回调中传递整个组件是危险的,可能会导致新手开发人员做出非常奇怪的事情,例如调用childComponent.setState(...) or childComponent.forceUpdate(),或者在父级内部为其分配新变量,使整个应用程序更难以推理。


编辑:ES6 示例

由于现在很多人使用 ES6,这里是 ES6 语法的相同示例

孩子可以很简单:

const Child = ({
  onClick, 
  text
}) => (
  <button onClick={onClick}>
    {text}
  </button>
)

父级可以是一个类(它最终可以管理状态本身,但我将它作为 props 在这里传递:

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>
)

JsFiddle


性能警告(适用于 ES5/ES6):如果您使用PureComponent or shouldComponentUpdate,默认情况下上述实现不会被优化,因为使用onClick={e => doSomething()},或者在渲染阶段直接绑定,因为每次父渲染时它都会创建一个新函数。如果这是应用程序中的性能瓶颈,您可以将数据传递给子级,然后将其重新注入到“稳定”回调中(在父类上设置,并绑定到this在类构造函数中)这样PureComponent优化可以启动,或者您可以实现自己的shouldComponentUpdate并忽略 props 比较检查中的回调。

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

// 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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 React.js 中将 props 传递给父组件 的相关文章

随机推荐