如何通过可选的标记参数将 onClick 处理程序从父组件传递到子组件

How to pass onClick handler from parent to child components through optional labeled arguments

我想将事件处理程序从父级传递给子级的一系列组件。这是一个工作示例:

Index.re

ReactDOMRe.renderToElementWithId(
  <App myHandler={_evt => Js.log("my handler clicked")} />,
  "root",
);

App.re

let component = ReasonReact.statelessComponent(__MODULE__);

let make = (~myHandler, _children) => {
  ...component,
  render: _self => <MyComponent myHandler />,
};

MyComponent.re

let component = ReasonReact.statelessComponent(__MODULE__);

let make = (~myHandler, _children) => {
  ...component,
  render: _self =>
    <div onClick=myHandler> {ReasonReact.string("click me")} </div>,
}

就像现在的代码一样,每个组件使用时都需要 myHandler 参数,否则我们会收到错误消息:

This call is missing an argument of type (~myHandler: ReactEvent.Mouse.t => unit)

通过在函数声明中添加 =? 可以使带标签的参数可选,如下所示:

let component = ReasonReact.statelessComponent(__MODULE__);

let make = (~myHandler=?, _children) => {
  ...component,
  render: _self =>
    <div onClick=myHandler> {ReasonReact.string("click me")} </div>,
};

然而这给出了一个编译错误:

  5 │   ...component,
  6 │   render: _self =>
  7 │     <div onClick=myHandler> {ReasonReact.string("click me")} </div>,
  8 │ };

  This has type:
    option('a)
  But somewhere wanted:
    ReactEvent.Mouse.t => unit

我认为编译器可能需要提示。因此,我尝试将该类型显式添加到函数声明中,如下所示:

let component = ReasonReact.statelessComponent(__MODULE__);

let make = (~myHandler: ReactEvent.Mouse.t => unit=?, _children) => {
  ...component,
  render: _self =>
    <div onClick=myHandler> {ReasonReact.string("click me")} </div>,
};

但随后错误发生在我身上并给了我:

  4 │ let make = (~myHandler: ReactEvent.Mouse.t => unit=?, _children) => {
  5 │   ...component,
  6 │   render: _self =>

  This pattern matches values of type
    ReactEvent.Mouse.t => unit
  but a pattern was expected which matches values of type
    option('a)

现在我很困惑。

因此,要使可选参数起作用,您必须在 MyComponent 组件中处理可选大小写本身。

let component = ReasonReact.statelessComponent(__MODULE__);

let make = (~myHandler=?, _children) => {
   ...component,
   render: _self => {
      let myHandler = switch myHandler {
        | None => (_e) => Js.log("default");
        | Some(handler) => handler;
   };
   <div onClick=myHandler> {ReasonReact.string("click me")} </div>
}

只是为了提供一个正确的答案,因为这似乎不太可能作为重复关闭

可选参数在被调用方方面变成了option。否则,您将如何表示没有论点。请记住,没有空值,因此必须明确表达可空性。

myHandler 因此是 option(ReactEvent.Mouse.t => unit)onClick 当然也是一个可选参数,它将被转换为 option,但由于这是通常自动完成的,我们不能直接将 option 提供给它。

幸运的是,有人已经想到了这种情况并添加了一个语法结构,以便能够将 option 作为可选参数显式传递。只需在传递给参数的表达式前添加一个 ?,你应该就可以了:

<div onClick=?myHandler> {ReasonReact.string("click me")} </div>,