我试图找到正确的方法来定义一些组件,这些组件可以以通用的方式使用:

<Parent>
  <Child value="1">
  <Child value="2">
</Parent>

当然,在父组件和子组件之间呈现有一个逻辑,您可以想象<select>和<option>是这个逻辑的一个例子。

这是为了解决这个问题的一个虚拟实现:

var Parent = React.createClass({
  doSomething: function(value) {
  },
  render: function() {
    return (<div>{this.props.children}</div>);
  }
});

var Child = React.createClass({
  onClick: function() {
    this.props.doSomething(this.props.value); // doSomething is undefined
  },
  render: function() {
    return (<div onClick={this.onClick}></div>);
  }
});

问题是无论何时使用{this.props。Children}定义一个包装器组件,如何将某些属性传递给它的所有子组件?


当前回答

允许你进行属性转移的最好方法是像函数模式一样的子元素 https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9

代码片段:https://stackblitz.com/edit/react-fcmubc

例子:

const Parent = ({ children }) => {
    const somePropsHere = {
      style: {
        color: "red"
      }
      // any other props here...
    }
    return children(somePropsHere)
}

const ChildComponent = props => <h1 {...props}>Hello world!</h1>

const App = () => {
  return (
    <Parent>
      {props => (
        <ChildComponent {...props}>
          Bla-bla-bla
        </ChildComponent>
      )}
    </Parent>
  )
}

其他回答

试试这个

<div>{React.cloneElement(this.props.children, {...this.props})}</div>

我用react-15.1就能做到。

使用{…这个。Props}建议在https://reactjs.org/docs/jsx-in-depth.html#spread-attributes

你不再需要{this.props.children}。现在你可以在Route中使用render来包装你的子组件,并像往常一样传递你的道具:

<BrowserRouter>
  <div>
    <ul>
      <li><Link to="/">Home</Link></li>
      <li><Link to="/posts">Posts</Link></li>
      <li><Link to="/about">About</Link></li>
    </ul>

    <hr/>

    <Route path="/" exact component={Home} />
    <Route path="/posts" render={() => (
      <Posts
        value1={1}
        value2={2}
        data={this.state.data}
      />
    )} />
    <Route path="/about" component={About} />
  </div>
</BrowserRouter>

我确实努力让列出的答案工作,但失败了。最终,我发现问题在于正确地建立亲子关系。仅仅在其他组件中嵌套组件并不意味着存在父子关系。

例1。亲子关系;

function Wrapper() {
  return (
    <div>
      <OuterComponent>
        <InnerComponent />
      </OuterComponent>
    </div>
  );
}
function OuterComponent(props) {
  return props.children;
}
function InnerComponent() {
  return <div>Hi! I'm in inner component!</div>;
}
export default Wrapper;

例2。嵌套的组件:

function Wrapper() {
  return (
    <div>
      <OuterComponent />
    </div>
  );
}
function OuterComponent(props) {
  return <InnerComponent />
}
function InnerComponent() {
  return <div>Hi! I'm in inner component!</div>;
}
export default Wrapper;

如上所述,道具传递在例1中有效。

下面的文章对此进行了解释https://medium.com/@justynazet/passing-props-to-props-children-using-react-cloneelement- andrend-props -pattern-896da70b24f6

也许您还可以发现这个特性很有用,尽管许多人认为这是一种反模式,但如果您知道自己在做什么并设计好解决方案,那么仍然可以使用它。

作为子组件的功能

在我的情况下,React.cloneElement()给了我很多问题,我使用Typescript的函数组件,所以我用孩子(道具)作为一种方式来传递我的道具给我的孩子元素。同样,我的情况非常独特,我必须传递给父组件一个属性,然后基于该属性,它将某些道具传递给子组件。这可以在一个简单的CodeSandbox示例中看到

App.tsx

import "./styles.css";
import Parent from "./Parent";

export default function App() {
  return (
    <>
      <Parent title={"With div wrapper"}>
        {({ title }) => <h1>{title}</h1>}
      </Parent>

      <Parent>
        {({ title }) => <h1>{title === undefined && "this is undefined"}</h1>}
      </Parent>
    </>
  );
}

Parent.tsx

export interface ChildrenProps {
  title?: string;
}

interface ParentWrapperProps {
  children: (title: ChildrenProps) => JSX.Element;
  title?: string;
}

const ParentWrapper: React.FC<ParentWrapperProps> = ({ children, title }) => {
  return title ? (
    <div>{children({ title: title })}</div>
  ) : (
    <>{children({ title: undefined })}</>
  );
};

export default ParentWrapper;