switch to immer.js
This commit is contained in:
+8
-7
@@ -5,34 +5,35 @@ import api from '../api-stub.js';
|
||||
const load_notes = function(state, dispatch){
|
||||
api.post('/load-notes', {bin_id: state.bin.id})
|
||||
.then(res=>{
|
||||
dispatch({type: 'notes-loaded', notes: res.notes, bin_id: state.bin.id});
|
||||
dispatch({type: 'notes-loaded', payload: res.notes});
|
||||
});
|
||||
};
|
||||
const runSearch = function(state, dispatch){
|
||||
api.post('/search', {search_term: state.search_term, sorting: state.sorting, bin_id: state.bin.id})
|
||||
.then(res=>{
|
||||
dispatch({type:'update-search-results', notes: res.notes});
|
||||
dispatch({type:'update-search-results', payload: res.notes});
|
||||
});
|
||||
};
|
||||
const new_note_handler = function(state, dispatch){
|
||||
dispatch({type:'add-note', id: nanoid()});
|
||||
dispatch({type:'add-note', payload:{id: nanoid(), date: Date.now()}});
|
||||
};
|
||||
const search_term_change_handler = function(state, dispatch, e){
|
||||
if(e.code === 'Enter'){
|
||||
runSearch(state, dispatch);
|
||||
}
|
||||
else{
|
||||
dispatch({type:'update-search-term', search_term: e.target.value});
|
||||
dispatch({type:'update-search-term', payload: e.target.value});
|
||||
}
|
||||
};
|
||||
const sorting_change_handler = function(state, dispatch, e){
|
||||
runSearch(state, dispatch);
|
||||
dispatch({type:'update-sorting', sorting: e.target.value});
|
||||
dispatch({type:'update-sorting', payload: e.target.value});
|
||||
};
|
||||
const new_bin_handler = function(state, dispatch){
|
||||
const id = nanoid();
|
||||
dispatch({type: 'new-bin', bin: {id}});
|
||||
dispatch({type: 'notes-loaded', notes: [], bin_id: id});
|
||||
// TODO: consolidate: this will cause two redraws:
|
||||
dispatch({type: 'new-bin', payload:{id}});
|
||||
dispatch({type: 'notes-loaded', payload: []});
|
||||
};
|
||||
|
||||
export {new_note_handler, search_term_change_handler, sorting_change_handler, load_notes, new_bin_handler};
|
||||
+3
-6
@@ -2,19 +2,16 @@
|
||||
import api from '../api-stub.js';
|
||||
|
||||
const edit_handler = function(note_state, dispatch){
|
||||
dispatch({type: 'update-note-editing', note_id: note_state.note.id, is_editing: true});
|
||||
dispatch({type: 'update-note-editing', payload:{id: note_state.note.id, is_editing: true}});
|
||||
};
|
||||
const cancel_handler = function(note_state, dispatch){
|
||||
dispatch({type: 'update-note-editing', note_id: note_state.note.id, is_editing: false});
|
||||
dispatch({type: 'update-note-editing', payload:{id: note_state.note.id, is_editing: false}});
|
||||
};
|
||||
const text_change_handler = function(note_state, dispatch, e){
|
||||
note_state.temp_text = e.target.value;
|
||||
};
|
||||
const save_handler = function(note_state, dispatch){
|
||||
// TODO: consolidate: this will cause two redraws:
|
||||
dispatch({type: 'update-note-text', note_id: note_state.note.id, text: note_state.temp_text});
|
||||
//note.text = temp_text;
|
||||
dispatch({type: 'update-note-editing', note_id: note_state.note.id, is_editing: false});
|
||||
dispatch({type: 'save-note-edit', payload:{id: note_state.note.id, text: note_state.temp_text}});
|
||||
api.post('/save', {bin_id: note_state.bin_id, note_id: note_state.note.id, text: note_state.temp_text})
|
||||
};
|
||||
|
||||
|
||||
Vendored
+2
File diff suppressed because one or more lines are too long
+1
-1
@@ -8,9 +8,9 @@
|
||||
<!--<link rel="stylesheet" href="animate.min.css"></link>-->
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!--<script src="./mithril.min.js"></script>-->
|
||||
<script src="./mithril.min.js"></script>
|
||||
<script src="./redux.min.js"></script>
|
||||
<script src="./immer.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module" src="./index.js"></script>
|
||||
|
||||
@@ -1,72 +1,29 @@
|
||||
import App from './App.js';
|
||||
import nanoid from './nanoid.min.js';
|
||||
const produce = immer.produce;
|
||||
immer.setAutoFreeze(false); // needed for high-frequency updated values, like onkeyup->note.temp_text; only once 'save' is called will it produce a new immutable state tree
|
||||
|
||||
var root = document.body;
|
||||
|
||||
function bin_reducer(old_state, new_state, action){
|
||||
if(action.type === 'new-bin'){
|
||||
new_state.bin = action.bin;
|
||||
}
|
||||
else{
|
||||
new_state.bin = old_state.bin;
|
||||
}
|
||||
}
|
||||
/* Ruthlessly taken from [https://gist.github.com/kitze/fb65f527803a93fb2803ce79a792fff8]: */
|
||||
const handleActions = (actionsMap, defaultState) =>
|
||||
(state=defaultState, {type, payload}) =>
|
||||
produce(state, draft => {
|
||||
const action = actionsMap[type];
|
||||
action && action(draft, payload);
|
||||
});
|
||||
|
||||
function search_reducer(old_state, new_state, action){
|
||||
if(action.type === 'update-search-term'){
|
||||
new_state.search_term = action.search_term;
|
||||
}
|
||||
else if(action.type === 'update-search-results'){
|
||||
new_state.notes = action.notes.map(note=>({is_editing: false, temp_text: '', bin_id: old_state.bin.id, note}));
|
||||
new_state.search_term = old_state.search_term;
|
||||
}
|
||||
else{
|
||||
new_state.search_term = old_state.search_term;
|
||||
}
|
||||
}
|
||||
|
||||
function notes_reducer(old_state, new_state, action){
|
||||
if(action.type === 'add-note'){
|
||||
new_state.notes = ([{is_editing: true, temp_text: '', bin_id: old_state.bin.id, note: {id: action.id, text: '', modified: Date.now()}}]).concat(old_state.notes)
|
||||
}
|
||||
else if(action.type === 'notes-loaded'){
|
||||
new_state.notes = action.notes.map(note=>({is_editing: false, temp_text: note.text, bin_id: action.bin_id, note}));
|
||||
}
|
||||
else if(action.type === 'update-note-text'){
|
||||
const i = old_state.notes.findIndex(note_state => note_state.note.id === action.note_id);
|
||||
new_state.notes = old_state.notes.slice();
|
||||
new_state.notes[i] = {...new_state.notes[i], note: {...new_state.notes[i].note, text: action.text, modified: Date.now()}};
|
||||
}
|
||||
else if(action.type === 'update-note-editing'){
|
||||
const i = old_state.notes.findIndex(note_state => note_state.note.id === action.note_id);
|
||||
new_state.notes = old_state.notes.slice();
|
||||
new_state.notes[i] = {...new_state.notes[i], is_editing: action.is_editing, temp_text: new_state.notes[i].note.text};
|
||||
}
|
||||
else{
|
||||
new_state.notes = old_state.notes;
|
||||
}
|
||||
}
|
||||
|
||||
function sorting_reducer(old_state, new_state, action){
|
||||
if(action.type === 'update-sorting'){
|
||||
new_state.sorting = action.sorting;
|
||||
}
|
||||
else{
|
||||
new_state.sorting = old_state.sorting;
|
||||
}
|
||||
}
|
||||
|
||||
function reducer(old_state, action){
|
||||
const new_state = {};
|
||||
bin_reducer(old_state, new_state, action);
|
||||
notes_reducer(old_state, new_state, action);
|
||||
search_reducer(old_state, new_state, action);
|
||||
sorting_reducer(old_state, new_state, action);
|
||||
return new_state;
|
||||
}
|
||||
|
||||
// create Redux store, with Redux DevTools enabled:
|
||||
const store = Redux.createStore(reducer, /* preloadedState, */ {
|
||||
const reducer = handleActions({
|
||||
'new-bin': (s, bin) => s.bin=bin,
|
||||
'update-search-term': (s, search_term) => { s.search_term=search_term; },
|
||||
'update-search-results': (s, _notes) => { s.notes =_notes.map(n=>({is_editing: false, temp_text: '', bin_id: s.bin.id, note:n})); },
|
||||
'add-note': (s, {id, date}) => { s.notes.unshift({is_editing: true, temp_text: '', bin_id: s.bin.id, note: {id: id, text: '', modified: date}}); },
|
||||
'notes-loaded': (s, _notes) => { s.notes = _notes.map(n=>({is_editing: false, temp_text: n.text, bin_id: s.bin_id, note:n})); },
|
||||
'update-note-text': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note.id===id); note_s.note.text=text; }, // updates underlying note text (i.e. the "model", not the app note_state) "in the background" (e.g. from a server-pushed update), regardless of whether it's being edited; "save" is a separate action, below
|
||||
'update-note-editing': (s, {id, is_editing}) => { const note_s=s.notes.find(n=>n.note.id===id); note_s.is_editing=is_editing; note_s.temp_text=note_s.note.text; },
|
||||
'save-note-edit': (s, {id, text}) => { const note_s=s.notes.find(n=>n.note.id===id); note_s.note.text=text; note_s.temp_text=text; note_s.is_editing=false; },
|
||||
'update-sorting': (s, sorting) => { s.sorting=sorting; }
|
||||
}, {
|
||||
bin: {id: nanoid()},
|
||||
notes: [
|
||||
//{is_editing: false, temp_text: '', bin_id: '', note: {id: nanoid(), text: 'Note one', modified: 1}},
|
||||
@@ -74,7 +31,10 @@ const store = Redux.createStore(reducer, /* preloadedState, */ {
|
||||
search_term: '',
|
||||
sorting: 'new->old'
|
||||
//search_result_notes: []
|
||||
},
|
||||
});
|
||||
|
||||
// create Redux store, with Redux DevTools enabled:
|
||||
const store = Redux.createStore(reducer, /* preloadedState, */
|
||||
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
|
||||
const dispatch = function(...args){ store.dispatch(...args); };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user