【问题标题】:Child Component Making Use of Parents' Prop in ReactJS子组件在 ReactJS 中使用父母的 Prop
【发布时间】:2020-01-12 03:01:43
【问题描述】:

我正在创建一个表单组件,它有一个Form 组件和一个Input 组件。像这样的:

<Form>
  <Input name="name" />
  <Input name="email" />
</Form>

在我的设置中,标签是从 name 属性自动生成的。不过,我想做的是提供一个不显示标签的选项。现在,我可以像这样在每个 &lt;Input&gt; 组件上执行此操作:

<Form>
  <Input noLabel name="name" />
  <Input noLabel name="email" />
</Form>

但我真正想做的是将它添加到&lt;Form&gt; 组件并让它自动应用于每个&lt;Input&gt; 组件。像这样的:

<Form noLabel>
  <Input name="name" />
  <Input name="email" />
</Form>

按照我的设想,在定义 &lt;Input&gt; 组件时,我可以检查是否在 &lt;Form&gt; 组件上设置了 noLabel 属性。像这样的:

export const Input = props => {
  ...
  {!props.noLabel && <label>...}
  <input.../>
  ...
}

但我不知道如何从 &lt;Form&gt; 组件中访问 noLabel 属性,以便检查它是否已设置。

关于如何做到这一点的任何想法?

【问题讨论】:

  • 你用的是什么版本的 react?是 16.4 及更高版本吗?
  • 我使用的是 16.8.6

标签: reactjs react-props react-component


【解决方案1】:

我会选择上下文方法,以克服我在对 Mohamed 解决方案的评论中提到的问题,这也将启用间接嵌套:

const FormContext = React.createContext();

const Form = ...;

Form.Context = FormContext; // or simply Form.Context = React.createContext();

export default ({noLabel, ...props}) => <FormContext.Provider value={{noLabel}}/>;

然后您的输入组件将像这样使用它:

const Input = props => {
  const {noLabel} = useContext(Form.Context);

  return (... < your no label logic here > ...);
}

或者像这样:

const Input = ....;

export default props => () => {
  const {noLabel} = useContext(Form.Context);

  return <Input noLabel={noLabel}/>
}

【讨论】:

  • 谢谢 Meir -- 我喜欢使用上下文的想法。非常优雅。
【解决方案2】:

一种方法是操纵formchildren。映射每一个并注入noLabelprop。您仍然需要在Input 内部查看noLabel prop,但工作量肯定会减少

const Form = ({children, noLabel}) =>{
    return React.children.forEach(_, child =>{
        return React.cloneElement(child, { noLabel })
    })
} 

【讨论】:

  • 谢谢——请注意我对 Mohamed 回答的评论——正如你所指出的,这与你的回答相同:)。
  • 这就像映射一个数组。只要您的表单没有荒谬的inputs 数量,这不会是性能问题
【解决方案3】:

在您的Form 组件中,您可以使用React.ChildrenReact.cloneElementnoLabel 属性传递给输入组件,如下所示:

const children = React.Children.map(this.props.children, child =>
  React.cloneElement(child, { noLabel: this.props.noLabel  })
);

return (<form>{children}</form>);

【讨论】:

  • 看来我们已经在这里同步了我们的想法啊哈哈哈哈
  • 这种方法有什么缺点吗?即,在性能或其他方面?即,我仅在 Form 组件上使用一个道具所获得的收益是否会在性能或与这样做相关的其他成本方面有所损失?
  • @Moshe 我认为这种方法有两个问题:1. 如果元素不是&lt;Input...&gt;,则无需复制它,然后添加一个可能引发错误的字段反应(反应可以抱怨带有无法识别名称的道具,例如 div、span 等) 2. Input 元素必须直接嵌套在表单中,任何中间布局元素(行、列等)都会破坏属性的传递
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-31
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 2018-12-20
相关资源
最近更新 更多