为什么在React组件中将功能作为子代传递?

时间:2019-11-27 11:28:39

标签: reactjs

我是React的新手,仍然在理解React组件的设计上仍然很努力。 我看到了一些如下代码:

export const ProModeContext = React.createContext();

export class XXX extends Component {
  ...
   render() {
      return <ProModeContext.Consumer>
              { contextData => {xxx }
             </ProModeContext.Consumer>
   }
}

模式是

<Abc>
{
   param => {xxx}   // let's say this anonymous arrow function is called f1
}
</Abc>

所以我的问题是:

Q1-是f1组件的子代,因此可以在组件内部以Abc的身份访问它吗?

Q2-如果this.props.childrenf1组件的子代,如何在Abc组件内调用f1

Abc

由于儿童道具不是数组,因此我们无法将export class Abcextends Component { ... this.props.children??? //how to invoke `f1` internally? } 调用为f1

2 个答案:

答案 0 :(得分:2)

从概念上讲,任何有效的JSX都是有效的JavaScript函数。 JavaScript函数接受JavaScript表达式或函数作为参数,这大致就是您执行操作

<h1>{ person.firstName }</h1> 

这里您创建了一个函数h1,它再次大致接受参数person.firstName

关于为什么不是所有props的问题,如果一切都是道具,那类似于使用回调。

通过使用父子模式,我们可以拥有一个更具声明性的UI。

现在,我们为什么要这样做?有很多原因,但是一个很好的理由是,在某些情况下,您不想为JSX项目列表声明变量就更加简洁。

您在下面提出了有关此模式的问题:

<Abc propName={param => xxx}>

此模式称为a render prop-当您希望将逻辑和渲染分开时,非常有用。

声明性模式和渲染道具模式服务于不同的用例,应在需要时将其应用于当前的问题,并且一个尺寸都不适合所有解决方案。

编辑: 您的第一个示例看起来像是从JSX编译为JavaScript

React.createElement(
    ABC, null, counts.map(count => React.createElement("p", null, count))
)

createElement的API如下:

React.createElement(
  type,
  [props],
  [...children]
)

答案 1 :(得分:0)

如果我没有误解您的问题,那么您是在询问render prop模式。

因此,当您希望父级在子级中做出一些渲染决定时,基本上使用渲染道具。例如:

<DataProvider render={data => (
  <h1>Hello {data.target}</h1>
)} id={someId}/>

这里假设DataProvider是一个仅基于id从某个API提取数据的组件。现在,获取后呈现的内容由render道具决定。因此,DataProvider的实现将是:

  • someId调用API。
  • 使用获取的数据调用render prop函数。

这种模式的一个用例是关注点分离。 DataProvider仅与获取数据有关。父母只关心渲染它。上面链接的官方文档中也描述了其他用例。

以孩子的身分通过:

function Parent() {
  return (
    <Child>
      <div>Some child content</div>
    </Child>
  );
}

function Child({ children }) {
  return <div>{children}</div>;
}

通过渲染道具传递:

function Parent() {
  return <Child render={(text) => <div>Some child {text}</div>} />;
}

function ChildWithRenderProp({ render }) {
  return <div>{render('content')}</div>;
}