Skip to content
This repository has been archived by the owner on Jul 16, 2020. It is now read-only.

Commit

Permalink
Fix todo item save bug; Move instanceVars to state
Browse files Browse the repository at this point in the history
  • Loading branch information
chenglou committed Apr 15, 2017
1 parent 6351a45 commit 6f2e7b1
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 32 deletions.
1 change: 1 addition & 0 deletions lib/js/src/todomvc/app.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 34 additions & 17 deletions lib/js/src/todomvc/todoItem.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/todomvc/app.re
Expand Up @@ -115,6 +115,7 @@ module Top = {
todo == todoToSave ? {...todo, TodoItem.title: text} : todo
)
state.todos;
saveLocally todos;
Some {...state, editing: None, todos}
};
let cancel {state} _ => Some {...state, editing: None};
Expand Down
38 changes: 23 additions & 15 deletions src/todomvc/todoItem.re
Expand Up @@ -5,7 +5,7 @@ let enterKey = 13;
type todo = {id: string, title: string, completed: bool};

module TodoItem = {
include ReactRe.Component.Stateful.InstanceVars;
include ReactRe.Component.Stateful;
let name = "TodoItemRe";
type props = {
todo,
Expand All @@ -16,47 +16,55 @@ module TodoItem = {
onToggle: unit => unit,
onCancel: unit => unit
};
type state = {editText: string};
type instanceVars = {mutable editFieldRef: option Dom.element};
let getInstanceVars () => {editFieldRef: None};
let getInitialState props => {editText: props.todo.title};
/* mutable state? Yes, that's right. In ReactJS we'd keep such `ref`,
subdescriptions, timerIDs and the rest attached into the component instance
itself (e.g. `this.editFieldRef`) in order to mutate them and circumvent re-
render (triggered by setState). Reason-React asks you to be more honest about
this: this pattern is effectively mutating internal state without causing a re-
render. */
type state = {editText: string, mutable editFieldRef: option Dom.element};
let getInitialState props => {editText: props.todo.title, editFieldRef: None};
let handleSubmit {props, state} _ =>
switch (String.trim state.editText) {
| "" =>
props.onDestroy ();
None
| nonEmptyValue =>
props.onSave nonEmptyValue;
Some {editText: nonEmptyValue}
Some {...state, editText: nonEmptyValue}
};
let handleEdit {props} _ /* event */ => {
let handleEdit {props, state} _ /* event */ => {
props.onEdit ();
Some {editText: props.todo.title}
Some {...state, editText: props.todo.title}
};
let handleKeyDown ({props} as componentBag) event =>
let handleKeyDown ({props, state} as componentBag) event =>
if (ReactEventRe.Keyboard.which event === escapeKey) {
props.onCancel ();
Some {editText: props.todo.title}
Some {...state, editText: props.todo.title}
} else if (
ReactEventRe.Keyboard.which event === enterKey
) {
handleSubmit componentBag ()
} else {
None
};
let handleChange {props} event =>
let handleChange {props, state} event =>
props.editing ?
Some {editText: (ReactDOMRe.domElementToObj (ReactEventRe.Form.target event))##value} : None;
let setEditFieldRef {instanceVars} r => instanceVars.editFieldRef = Some r;
Some {
...state,
editText: (ReactDOMRe.domElementToObj (ReactEventRe.Form.target event))##value
} :
None;
let setEditFieldRef {state} r => state.editFieldRef = Some r;

/**
* Safely manipulate the DOM after updating the state when invoking
* `props.onEdit()` in the `handleEdit` method above.
* For more info refer to notes at https://facebook.github.io/react/docs/component-api.html#setstate
* and https://facebook.github.io/react/docs/component-specs.html#updating-componentdidupdate
*/
let componentDidUpdate ::prevProps prevState::_ {props, instanceVars} =>
switch (prevProps.editing, props.editing, instanceVars.editFieldRef) {
let componentDidUpdate ::prevProps prevState::_ {props, state} =>
switch (prevProps.editing, props.editing, state.editFieldRef) {
| (false, true, Some field) =>
let node = ReactDOMRe.domElementToObj field;
ignore (node##focus ());
Expand Down

0 comments on commit 6f2e7b1

Please sign in to comment.