在无状态子组件中传递/访问道具

Posted

技术标签:

【中文标题】在无状态子组件中传递/访问道具【英文标题】:Passing/Accessing props in stateless child component 【发布时间】:2017-06-08 08:45:49 【问题描述】:

我知道你可以像这样将所有的 react 组件 props 传递给它的子组件:

const ParentComponent = () => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent ...this.props />
   </div>
)

但是如果子组件是无状态的,那么你如何检索这些道具呢?我知道如果它是一个类组件,您可以将它们作为this.prop.whatever 访问,但是您将什么作为参数传递给无状态组件?

const ChildComponent = ( *what goes here?* ) => (
   <div>
      <h1>Child Component</h1>
   </div>
)

【问题讨论】:

您是在使用功能组件还是类组件? 是的 - 我的设置和我在原帖中所说的一样 【参考方案1】:

当你写作时

const ChildComponent = ( someProp ) => (
   <div>
      <h1>Child Component someProp</h1>
   </div>
)

从你传递给childComponent 的所有道具中,你只是解构得到someProp。如果您想在 ChildComponents 中使用的道具数量在可用道具总数中是可数的(很少),那么解构是一个不错的选择,因为它提供了更好的可读性。

假设你想访问子组件中的所有道具,那么你不需要在参数周围使用,然后你可以像props.someProp一样使用它

const ChildComponent = (props) => (
   <div>
      <h1>Child Component props.someProp</h1>
   </div>
)

【讨论】:

【参考方案2】:

您是否在寻找 ES6 命名参数语法(仅仅是解构)?

const ChildComponent = ( propName ) => (
    <div>
     <h1>Child Component</h1>
 </div>
)

const ChildComponent = (props) => ( // without named arguments
    <div>
     <h1>Child Component</h1>
 </div>
)

根据您是否为组件指定了 context,您的函数还有第二个参数(可选)。

也许链接到docs 会更有帮助。正如第一篇关于功能组件的文章所述。传递给组件的任何道具都表示为作为第一个参数传递给功能组件的对象。

更进一步,关于 jsx 中的扩展符号。

当你写在一个组件中时:

<Child prop1=value1 prop2=value2 />

您的组件将收到一个普通对象,如下所示:

 prop1: value1, prop2: value2 

(注意它不是 Map,而是一个只有字符串作为键的对象)。

因此,当您将 spread 语法与 JS 对象一起使用时,它实际上是一个快捷方式

const object =  key1: value1, key2: value2 
<Component ...object/>

相当于

<Component key1=value1 key2=value2 />

并实际编译为

return React.createElement(Component, object); // second arg is props

你当然可以使用第二种语法,但要注意顺序。更具体的语法 (prop=value) 必须在最后:更具体的指令在最后。

如果你这样做:

<Component key=value ...props />

编译成

React.createElement(Component, _extends( key: value , props));

如果你这样做(你可能应该这样做)

<Component ...props key=value />

编译成

React.createElement(Component, _extends(props,  key: value ));

extends 是 *Object.assign (如果不存在,则为 polyfill)。

为了更进一步,我真的建议花一些时间来观察 Babel 的输出及其online editor。这对于理解 jsx 是如何工作的,以及更一般地如何使用 ES5 工具实现 es6 语法非常有趣。

【讨论】:

实际上我试图避免列出父组件中的所有单个道具,因为它很冗长。所以我想使用...this.props 语法。我只是不知道如何在子组件中访问这些。【参考方案3】:
const ParentComponent = (props) => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent ...props />
   </div>
);

const ChildComponent = (prop1, ...rest) =>
  <div>
    <h1>Child Component with prop1=prop1</h1>
    <GrandChildComponent ...rest />
  </div>


const GrandChildComponent = (prop2, prop3)=> 
  <div>
    <h1>Grand Child Component with prop2=prop1 and prop3=prop3</h1>
  </div>

【讨论】:

【参考方案4】:

您可以使用扩展属性来减少代码膨胀。这以'somearg':123, ...props...this.props 的形式出现,前者允许您设置一些字段,而后者是完整的副本。这是ParentClass.js 的示例:

import React from 'react';
import SomeComponent from '../components/SomeComponent.js';

export default class ParentClass extends React.Component 
    render() 
        <SomeComponent
            ...this.props
        />
    

如果我这样做,&lt;ParentClass getCallBackFunc=() =&gt; this.getCallBackFunc() /&gt;,或者如果我这样做&lt;ParentClass date=todaysdatevar /&gt;getCallBackFuncdate 的属性将可用于 SomeComponent 类。这为我节省了大量的打字和/或复制/粘贴。

来源:ReactJS.org: JSX In Depth, Specifying the React Element Type, Spread Attributes。官方 POD:

如果你已经有 props 作为对象,并且你想在 JSX 中传递它,你可以使用 ... 作为“扩展”运算符来传递整个 props 对象。这两个组件是等价的:

 return <Greeting firstName="Ben" lastName="Hector" />;


function App2() 
 const props = firstName: 'Ben', lastName: 'Hector';
 return <Greeting ...props />;
```

现在,让我们将其应用于您的代码示例!

const ParentComponent = (props) => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent ...props />
   </div>
);

【讨论】:

【参考方案5】:

我想我会添加一个简单的 ES2015 解构语法,用于将所有道具从功能性父组件传递到功能性子组件。

const ParentComponent = (props) => (
  <div>
    <ChildComponent ...props/>
  </div>
);

或者如果我有多个对象(父母的道具,加上其他任何东西),我想作为道具传递给孩子:

const ParentComponent = (...props, ...objectToBeAddedToChildAsProps) => (
  <div>
    <ChildComponent ...props/>
  </div>
);

这种解构语法类似于上面的答案,但它是我从功能组件传递道具的方式,我认为它真的很干净。希望对你有帮助!

【讨论】:

【参考方案6】:

但是如果子组件是无状态的,那么你如何检索这些道具呢?

const ChildComponent = ( *what goes here?* ) => (
   <div>
      <h1>Child Component</h1>
   </div>
)

ChildComponent 保存名称,props 将是箭头函数语法中的参数,就像您需要的那样:

 const ChildComponent = props => (
   <div>
     <p>props.value ? props.value : "No value."</p>
   </div>
 );

如果您使用 Babel-it,它将创建如下内容:

 var ChildComponent = function ChildComponent(props) 
   return React.createElement(
     "div",
     null,
     React.createElement(
       "p",
       null,
       props.value ? props.value : "No value."
     )
   );
 ;

【讨论】:

【参考方案7】:

出于某种原因,似乎对我有用的是Shubham's answer above 的变体:

const ChildComponent = props => (
   <div>
      <h1>Child Component props[0].someProp</h1>
   </div>
)

【讨论】:

【参考方案8】:

使用这个

const ParentComponent = ( prop1, prop2, prop3 ) => (
   <div>
     <h1>Parent Component</h1>
     <ChildComponent ... prop1, prop2, prop3  />
   </div>
);

const ChildComponent = ( prop1, prop2, prop3 ) =>
  <div>
    <h1>Child Component with prop1=prop1</h1>
    <h1>Child Component with prop2=prop2</h1>
    <h1>Child Component with prop2=prop3</h1>
  </div>

【讨论】:

我看到“prop1, prop2, prop3”在这里重复出现了好几次。我认为这个想法是在没有每次实际复制/粘贴参数列表的情况下产生这种效果。

以上是关于在无状态子组件中传递/访问道具的主要内容,如果未能解决你的问题,请参考以下文章

在无状态组件上添加默认道具

在无状态组件内传递函数不起作用

使用钩子在无状态组件中获得子状态

在 React 的子组件中将状态作为道具传递

将状态作为道具传递给子组件不起作用

将道具传递给***组件中的状态