如何在原因反应绑定中跨组件构成道具?

时间:2017-11-06 10:12:37

标签: material-ui ffi reason bucklescript reason-react

我目前正在编写一个材质-UI理由反应绑定,我想知道如何重新使用之前定义的Props。

Select组件将所有Input props分散到底层的react-js lib中。这是通过传播道具来完成的,但是在ReasonML中不鼓励因为打字丢失了。

作为临时解决方案,我已将道具从一个复制到另一个,但这不可扩展。如果有人能在Reason-React中建议这样做的正确方法,我将不胜感激?

由于

输入模块定义:

module Input = {
  [@bs.module "material-ui/Input"] external reactClass : ReasonReact.reactClass = "default";
  let make =
      (
        ~disableUnderline: option(bool)=?,
        ~disabled: option(bool)=?,
        ~error: option(bool)=?,
        ~autoFocus: option(bool)=?,
        ~fullWidth: option(bool)=?,
        ~style: option(ReactDOMRe.style)=?,
        ~value: option(string)=?,
        ~onChange: option((ReactEventRe.Form.t => unit))=?,
        ~placeholder: option(string)=?,
        ~className: option(string)=?,
        ~inputType: option(string)=?,
        children
      ) =>
    ReasonReact.wrapJsForReason(
      ~reactClass,
      ~props=
        Js.Nullable.(
          {
            "disableUnderline": unwrap_bool(disableUnderline),
            "disabled": unwrap_bool(disabled),
            "error": unwrap_bool(error),
            "fullWidth": unwrap_bool(fullWidth),
            "autoFocus": unwrap_bool(autoFocus),
            "style": from_opt(style),
            "placeholder": from_opt(placeholder),
            "className": from_opt(className),
            "type": from_opt(inputType),
            "value": from_opt(value),
            "onChange": from_opt(onChange)
          }
        ),
      children
    );
};

选择模块定义:

    module Select = {
  [@bs.module "material-ui/Select"] external reactClass :  ReasonReact.reactClass = "default";
  let make =
      (
        ~autoWidth: option(bool)=?,
        ~classes: option(Js.t({..}))=?,
        ~className: option(string)=?,
        ~displayEmpty: option(bool)=?,
        ~input: option(ReasonReact.reactElement)=?,
        ~inputClasses: option(Js.t({..}))=?,
        ~native: option(bool)=?,
        ~multiple: option(bool)=?,
        ~menuProps: option(Js.t({..}))=?,
        ~renderValue: option((unit => unit)),
        ~value: option('a)=?,
        ~style: option(ReactDOMRe.style)=?,
        /* Input Props*/
        ~disableUnderline: option(bool)=?,
        ~disabled: option(bool)=?,
        ~error: option(bool)=?,
        ~autoFocus: option(bool)=?,
        ~fullWidth: option(bool)=?,
        ~value: option(string)=?,
        ~onChange: option((ReactEventRe.Form.t => unit))=?,
        ~placeholder: option(string)=?,
        ~className: option(string)=?,
        ~inputType: option(string)=?,
        children
      ) =>
    ReasonReact.wrapJsForReason(
      ~reactClass,
      ~props=
        Js.Nullable.(
          {            
            "autoWidth": unwrap_bool(autoWidth),
            "classes": from_opt(classes),
            "className": from_opt(className),
            "displayEmpty": unwrap_bool(displayEmpty),
            "input": from_opt(input),
            "InputClasses": from_opt(inputClasses),
            "native": unwrap_bool(native),
            "multiple": unwrap_bool(multiple),
            "MenuProps": from_opt(menuProps),
            "renderValue": from_opt(renderValue),
            "value": from_opt(value),
            "style": from_opt(style),
            /* Input Props*/
            "disableUnderline": unwrap_bool(disableUnderline),
            "disabled": unwrap_bool(disabled),
            "error": unwrap_bool(error),
            "fullWidth": unwrap_bool(fullWidth),
            "autoFocus": unwrap_bool(autoFocus),
            "style": from_opt(style),
            "placeholder": from_opt(placeholder),
            "className": from_opt(className),
            "type": from_opt(inputType),
            "value": from_opt(value),
            "onChange": from_opt(onChange)
          }
        ),
      children
    );
};

1 个答案:

答案 0 :(得分:3)

您可以使用currying和Js.Obj.assign来实现此目的:

let common = (reactClass, props, ~commonProp1, ~commonProp2, children) =>
  ReasonReact.wrapJsForReason(
    ~reactClass,
    ~props=Js.Obj.assign(props, {
      "commonProp1": commonProp1,
      "commonProp2": commonProp2
    }),
    children
  );

module Input = {
  [@bs.module "material-ui/Input"] external reactClass :  ReasonReact.reactClass = "default";
  let make = (~inputProp1, ~inputProp2) => common(reactClass, {
    "inputProp1": inputProp1,
    "inputProp2": inputProp2
  });
};

module Select = {
  [@bs.module "material-ui/Select"] external reactClass :  ReasonReact.reactClass = "default";
  let make = (~selectProp1, ~selectProp2) => common(reactClass, {
    "selectProp1": selectProp1,
    "selectProp2": selectProp2
  });
};

在每个make函数中common部分应用,并且由于currying将会延长" make函数有自己的参数。实际上,例如, Input.make将为~inputProp1 => ~inputProp2 => ~commonProp1 => ~commonProp2 => ...