Skip to content

Instantly share code, notes, and snippets.

@Zerim
Last active February 19, 2018 23:25
Show Gist options
  • Save Zerim/6ff94ae1897d65bfbdae7279860bd43a to your computer and use it in GitHub Desktop.
Save Zerim/6ff94ae1897d65bfbdae7279860bd43a to your computer and use it in GitHub Desktop.
A simple SignupForm written in ReasonML
/* `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>
};
@yawaramin
Copy link

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)>

@rickyvetter
Copy link

rickyvetter commented Sep 22, 2017

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.

@Zerim
Copy link
Author

Zerim commented Sep 23, 2017

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.

@Zerim
Copy link
Author

Zerim commented Sep 23, 2017

Was thinking something like: onChange=(self.ReasonReact.reduce (compose UpdateEmail getEventTargetValue))

@rickyvetter
Copy link

@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.

@Zerim
Copy link
Author

Zerim commented Sep 25, 2017

Thanks @rickyvetter, forgot I could rely on type inference instead of explicitly annotating there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment