Reactjs 子组件利用父组件';道具
我正在创建一个表单组件,它将有一个Reactjs 子组件利用父组件';道具,reactjs,react-props,react-component,Reactjs,React Props,React Component,我正在创建一个表单组件,它将有一个表单组件和一个输入组件。大概是这样的: <Form> <Input name="name" /> <Input name="email" /> </Form> <Form> <Input noLabel name="name" /> <Input noLabel name="email" /> </Form> <Form noLabel>
表单
组件和一个输入
组件。大概是这样的:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
但我真正想做的是将其添加到
组件中,并将其自动应用于每个
组件。大概是这样的:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
按照我的设想,在定义
组件时,我可以检查
组件上是否设置了noLabel属性。大概是这样的:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
export const Input=props=>{
...
{!props.noLabel&&…}
...
}
但是我不知道如何从
组件访问noLabel
道具,以便检查它是否已设置
关于如何执行此操作,您有什么想法吗?在您的
表单
组件中,您可以使用React.Children
和React.cloneElement
将noLabel
属性传递给输入组件,如下所示:
const children = React.Children.map(this.props.children, child =>
React.cloneElement(child, { noLabel: this.props.noLabel })
);
return (<form>{children}</form>);
const children=React.children.map(this.props.children,child=>
React.cloneElement(子级,{noLabel:this.props.noLabel})
);
返回({children});
在表单
组件中,您可以使用React.Children
和React.cloneElement
将noLabel
道具传递给输入组件,如下所示:
const children = React.Children.map(this.props.children, child =>
React.cloneElement(child, { noLabel: this.props.noLabel })
);
return (<form>{children}</form>);
const children=React.children.map(this.props.children,child=>
React.cloneElement(子级,{noLabel:this.props.noLabel})
);
返回({children});
一种方法是操纵表单
的子项
。映射到每个对象上,并注入noLabel
prop
。您仍然需要在输入
中检查无标签
道具
,但这肯定会减少工作量
const Form = ({children, noLabel}) =>{
return React.children.forEach(_, child =>{
return React.cloneElement(child, { noLabel })
})
}
一种方法是操纵
表单
的子项
。映射到每个对象上,并注入noLabel
prop
。您仍然需要在输入
中检查无标签
道具
,但这肯定会减少工作量
const Form = ({children, noLabel}) =>{
return React.children.forEach(_, child =>{
return React.cloneElement(child, { noLabel })
})
}
我将选择上下文方法,以克服我在对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 FormContext=React.createContext();
常数形式=。。。;
Form.Context=FormContext;//或者只是Form.Context=React.createContext();
导出默认值({noLabel,…props})=>;
然后您的输入组件将使用它,如下所示:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
const Input=props=>{
const{noLabel}=useContext(Form.Context);
返回(…<此处无标签逻辑>…);
}
或者像这样:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
const输入=。。。。;
导出默认道具=>()=>{
const{noLabel}=useContext(Form.Context);
返回
}
我会选择上下文方法,以克服我在对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 FormContext=React.createContext();
常数形式=。。。;
Form.Context=FormContext;//或者只是Form.Context=React.createContext();
导出默认值({noLabel,…props})=>;
然后您的输入组件将使用它,如下所示:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
const Input=props=>{
const{noLabel}=useContext(Form.Context);
返回(…<此处无标签逻辑>…);
}
或者像这样:
<Form>
<Input name="name" />
<Input name="email" />
</Form>
<Form>
<Input noLabel name="name" />
<Input noLabel name="email" />
</Form>
<Form noLabel>
<Input name="name" />
<Input name="email" />
</Form>
export const Input = props => {
...
{!props.noLabel && <label>...}
<input.../>
...
}
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}/>
}
const输入=。。。。;
导出默认道具=>()=>{
const{noLabel}=useContext(Form.Context);
返回
}
react的版本是什么?是否为16.4及更高版本?我使用的是16.8.6您使用的是什么版本的react?是16.4或更高版本吗?我使用的是16.8.6版本,就像我们在这里同步了我们的想法一样。哈哈,这种方法有什么缺点吗?也就是说,在性能或其他方面?也就是说,我在表单组件上仅使用一个道具所获得的收益是否在性能或与此相关的其他成本方面有所损失?@Moshe我认为这种方法有两个问题:1。如果元素不是
,则无需复制它,并且添加了一个可能会导致react出错的字段(react可能会向div、span等基本体抱怨具有无法识别名称的道具)。输入元素必须直接嵌套在表单中,任何中间布局元素(行、列等)都会中断属性的传递,就像我们在这里同步了我们的想法一样。这种方法有什么缺点吗?也就是说,在性能或其他方面?也就是说,我在表单组件上仅使用一个道具所获得的收益是否在性能或与此相关的其他成本方面有所损失?@Moshe我认为这种方法有两个问题:1。如果元素不是
,则无需复制它,并且添加了一个可能会导致react出错的字段(react可能会向div、span等基本体抱怨具有无法识别名称的道具)。输入元素必须直接嵌套在表单中,任何中间布局元素(行、列等)都会破坏属性库的传递--请注意我对Mohamed答案的评论--正如您所指出的,这与您的答案相同:)。这就像映射数组一样。只要你的表单没有荒谬的输入量
,这就不会是性能问题--请注意我对Mohamed答案的评论--正如你所指出的,它与你的答案相同:)。这就像映射数组一样。只要您的表单没有大量的输入
,这就不会是性能问题--我喜欢使用上下文的想法。非常优雅。谢谢梅尔——我喜欢使用上下文的想法。非常优雅。