简体   繁体   English

从props.children中提取组件?

[英]Extracting a component from props.children?

I was working on a Panel component in ReactJS, and so, idea is to make the basic components available along with the collapse/close functionality. 我当时在ReactJS中使用Panel组件,因此,想法是使基本组件与折叠/关闭功能一起可用。 However, I am unable to find any way to extract a component from this.props.children . 但是,我找不到任何从this.props.children提取组件的this.props.children

So here is my component: 所以这是我的组件:

import React, { Component } from 'react';
import Header from './PanelHeader';
import Body from './PanelBody';


class Panel extends React.Component {
   constructor(props) {
      super(props);
      this.state = { open: true };
   }


   render() {
      return (
        <StyledPanel>
          {this.props.children}   <-- Is there a way to extract the Header component here
        </StyledPanel>
      );
   }
}

Object.assign(Panel, 
{
  Header,
  Body
});

export default Panel;

So, now the user of this component can do something like: 因此,现在该组件的用户可以执行以下操作:

<Panel>
   <Panel.Header>Header text for this panel</Panel.Header>
   <Panel.Body>Body of this panel</Panel.Body>
</Panel>

Header component contains a toolbar control for collapse and close functionalities. Header组件包含用于折叠和关闭功能的工具栏控件。 Now I do understand that the user of this component can specify these event handlers, and implement these features. 现在,我知道该组件的用户可以指定这些事件处理程序,并实现这些功能。 But I want this out of the box. 但我想开箱即用。 So, Panel by default, should be able to collapse everything except the header. 因此, Panel默认情况下应该能够折叠标题以外的所有内容。 So is it possible to extract Header component inside the Panel from this.props.children ? 那么可以从this.props.children提取Panel内部的Header组件吗? If yes, then how? 如果是,那怎么办?

Also, if I did make this work by: 另外,如果我确实通过以下方式进行了此项工作:

  1. Iterating this.props.children until child.type === Header 迭代this.props.children直到child.type === Header
  2. Using React.cloneElement to assign new props 使用React.cloneElement分配新道具
  3. And passing in the new event handlers for these new features. 并传入这些新功能的新事件处理程序。

Am I doing something wrong here? 我在这里做错什么了吗? Or is there some elegant way to achieve this? 还是有一些优雅的方法来实现这一目标?

Thank you. 谢谢。

You could implement it as a higher-order component which would take header and body as parameters. 您可以将其实现为一个高阶组件,该组件将headerbody作为参数。 You could pass any header or body, the only restriction would be that header requires an onOpenChanged callback prop . 您可以传递任何标头或正文,唯一的限制是标头需要onOpenChanged回调prop

Here is a working sandbox . 这是一个工作中的沙箱

Link to HOC 链接到HOC

const Header = (props) =>{
  const { onOpenChanged } = props;
  return <div onClick={onOpenChanged}>Header text for this panel</div>;
}

const Body = () => <div>Body of this panel</div>;

const stylishPanel = (WrappedHeader, WrappedBody) => {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        isOpen: true
      };
    }
    handleToggleOpen = () => {
      this.setState(({ isOpen }) => ({
        isOpen: !isOpen
      }));
    };
    render() {
      const { isOpen } = this.state;
      // your styled-panel instead of div
      return (
        <div className="super-panel">
          <WrappedHeader onOpenChanged={this.handleToggleOpen} />
          {isOpen && <WrappedBody />}
        </div>
      );
    }
  };
};
const App = () => {
  const SuperPanel = stylishPanel(Header, Body);
  return (
    <div style={styles}>
       <SuperPanel />
    </div>
  );
};

render(<App />, document.getElementById("root"));

In case you want to extract a component from this.props.children , 如果要从this.props.children提取组件,

try to use Function as a Child / Render props pattern. 尝试使用“ 功能作为子代/渲染道具”模式。

the pattern is like this: 模式是这样的:

class MyComponent extends Component {
  state = {
    bgcolor: 'red'
  }

  render(){
    <div>
       { this.props.children(this.state.bgcolor)}
    </div>
  }
}

class App exnted Component {
  render(){
    <MyComponent> 
      { bgColor => <Header bgcolor={bgColor} /> }
    </MyComponent>
  }
}

See MyComponent is just a wrapper that passes a value to its function. 请参见MyComponent只是将值传递给其函数的包装器。 The function as written inside App component is just a stateless function/component, an arrow function that returns some JSX . App组件内部编写的函数只是一个无状态函数/组件,一个返回一些JSX的箭头函数。

The HOC pattern as mantioned above is also a way. 上面提到的HOC模式也是一种方法。

This is a known topic about those 2 patterns. 这是关于这两种模式的已知主题。 This article might shad some light in case your are not yet sure: https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce 如果您不确定,本文可能会有所帮助: https : //cdb.reacttraining.com/use-a-render-prop-50de598f11ce

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM