-
-
Save Zerim/6ff94ae1897d65bfbdae7279860bd43a to your computer and use it in GitHub Desktop.
/* `action` and `state` types must be defined before the `let component` statement for type inference to work */ | |
type action = | |
| UpdateEmail string | |
| UpdatePassword string; | |
type state = { | |
email: string, | |
password: string | |
}; | |
/* Wrap the variant constructor in function so they may be composed */ | |
let updateEmail email => UpdateEmail email; | |
let updatePassword password => UpdatePassword password; | |
let component = ReasonReact.reducerComponent "Signup"; | |
/* Or could destructure here (i.e. `let handleSubmit _ {ReasonReact.state} => Js.log state`) */ | |
let handleSubmit _ self => Js.log self.ReasonReact.state; | |
let getEventTargetValue event :string => ( | |
ReactDOMRe.domElementToObj ( | |
ReactEventRe.Form.target event | |
) | |
)##value; | |
let make _children => { | |
...component, | |
initialState: fun () => {email: "", password: ""}, | |
reducer: fun action state => | |
switch action { | |
| UpdateEmail value => ReasonReact.Update {...state, email: value} | |
| UpdatePassword value => ReasonReact.Update {...state, password: value} | |
}, | |
render: fun self => | |
<div className="Login"> | |
<div> <h2> (ReasonReact.stringToElement "Signup here") </h2> </div> | |
/* Call self.handle to access the latest value of `self.ReasonReact.state` in the callback. */ | |
<form onSubmit=(self.handle handleSubmit)> | |
<input | |
onChange=( | |
self.ReasonReact.reduce (fun event => event |> getEventTargetValue |> updateEmail) | |
) | |
placeholder="email" | |
/> | |
<input | |
onChange=(self.reduce (fun event => event |> getEventTargetValue |> updatePassword)) | |
placeholder="password" | |
/> | |
<input _type="submit" value="Register" /> | |
</form> | |
</div> | |
}; |
I know one things that could be made more concise is having a UpdatePassword
and UpdateEmail
actions instead of having separate variants for the field
type.
Looks great! Off the top of my head, you can design the form submit handler to be a bit more concise:
let handleSubmit state _ => Js.log state;
/* or let handleSubmit state _event => ... */
...
<form onSubmit=(handleSubmit self.state)>
handleSubmit self.state
will give you the state when the component was rendered - not necessarily the state when the button is clicked (guaranteed latest). If you want that you should use onSubmit=(self.handle handleSubmit)
which will provide most up-to-date state and the form to handleSubmit
.
Thanks for the feedback @yawaramin and @rickyvetter! Edits made.
I couldn't easily figure out how I should be typing self
in the handleSubmit
function by inspection (I used ReasonReact.self _ _ _
). Is that idiomatic or should I be putting something else there? Seemed to compile/work okay...
Also I was wondering if you though the onChange
callback could be made more concise through functional composition/ currying, but wasn't sure if that worked for Variant constructors.
Was thinking something like: onChange=(self.ReasonReact.reduce (compose UpdateEmail getEventTargetValue))
@Zerim - I'd use either of
let handleSubmit _ self => Js.log self.ReasonReact.state;
or
let handleSubmit _ {ReasonReact.state} => Js.log state;
depending on actual usecase. You can explicitly type if you'd like, but self does have a lot of baggage to carry around.
Thanks @rickyvetter, forgot I could rely on type inference instead of explicitly annotating there.
Right now, the onSubmit just does a simple console.log for testing purposes, but in theory could be used for any side-effect. Any pointers to make this example more idiomatic would be appreciated!