问题
I am currently writing a material-UI reason-react binding and I want to know how I can re-use previously define Props.
The Select component spreads all of the Input props into itself, in the underlying react-js lib. this is done by spreading props however this is discouraged in ReasonML as typings are lost.
As a temporary solution, I have copied the props from one to another but this is not scalable. I would appreciate if someone could suggest what is the correct way of doing this in Reason-React?
Thanks
Input module definiton:
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
);
};
Select module definiton:
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:
You can use currying and Js.Obj.assign
to achieve this:
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
});
};
In each make
function common
is partially applied, and due to currying will "extend" the make function with its own arguments. In effect, the type signature of e.g. Input.make
will be ~inputProp1 => ~inputProp2 => ~commonProp1 => ~commonProp2 => ...
.
来源:https://stackoverflow.com/questions/47134445/how-to-compose-props-across-component-in-reason-react-bindings