反应:在特定父项下强制子项

时间:2018-09-09 02:14:04

标签: reactjs

我有一个像这样的组件:

<Dialog id="_login" modal={true} onSubmit={() => console.log("x")} onCancel={() => console.log("C")} visible={true} >
    <DialogHead>
        Title Here
    </DialogHead>
    <DialogBody>
        <Field id="username" label="User Name" onChange={(id, value) => { console.log(id, value) }} />
        <Field id="password" label="Password" onChange={(id, value) => { console.log(id, value) }} />
    </DialogBody>
    <DialogFoot>
        <button onClick={e => console.log(e)}>Close</button>
    </DialogFoot>
</Dialog>

下面是<Dialog>渲染代码

public render() {
    return <div className="hx-dialog-outer" onClick={this.onCancel.bind(this)}>
        <div className="hx-dialog-inner" onClick={(e) => {e.stopPropagation()}}>
            <form name={this.props.id}>
                {this.props.children}
            </form>
        </div>
    </div>
}

如何在子元素下强制子元素?我的意思是<DialogHead><DialogBody><DialogFoot><Dialog>容器外无效。例如,如果按以下方式使用它,它将产生类似“ ERROR:DialogHead必须嵌套在Dialog组件中”的错误。

<div>
    <DialogHead>
        Title Here
    </DialogHead>
</div>

2 个答案:

答案 0 :(得分:1)

我认为您可以使用包含性的概念,其中对话框组件为:

function Dialog (props) {
  return (
    <div>
      {props.children}
    </div>
  );
}

现在您可以使用:

<Dialog id="_login" modal={true} onSubmit={() => console.log("x")} onCancel={() => console.log("C")} visible={true} >
    <DialogHead>
        Title Here
    </DialogHead>
    <DialogBody>
        <Field id="username" label="User Name" onChange={(id, value) => { console.log(id, value) }} />
        <Field id="password" label="Password" onChange={(id, value) => { console.log(id, value) }} />
    </DialogBody>
    <DialogFoot>
        <button onClick={e => console.log(e)}>Close</button>
    </DialogFoot>
</Dialog>

这是参考:Containment

答案 1 :(得分:0)

React Context API可能就是您想要的。

// Parent <Dialog/>
class Dialog extends React.Component {
  static childContextTypes = {
    dialog: PropTypes.object.isRequired
  }
  getChildContext() {
    return {
      dialog: this.props.dialog
    }
  }
}

// Children <DialogHeader/>, <DialogBody/>, <DialogFooter/>
const DialogHeader = (props, context) {
  if (context.dialog == null)
    throw new Error('You should not use <DialogHeader/> outside a <Dialog/>')
  // return some markup
}

DialogHeader.contextTypes = {
  dialog: PropTypes.object.isRequired
}

自从React 16.3+起有新的上下文API

const {Provider: DialogProvider, Consumer: DialogConsumer} = React.createContext(null)

const Dialog = props =>
  <DialogProvider value={{dialog: props.dialog}}>
    {props.children}
  </DialogProvider>

const DialogHeader = props =>
  <DialogConsumer>
    {({ dialog }) => 
      if (dialog == null) return new Error()
      // return some markup
    }
  </DialogConsumer>