..
Redux 리듀서 Clojure로 작성해보기
현재 Clojure에 대한 코드 블럭이 이상함. 나중에 수정 예정.
Javscript
const initialState = {
isLogBookOpen: false,
completedTasks: [],
selectedTaskId: 0,
parentId: 0,
nextTaskId: 1,
remainingTasks: {
0: { title: 'root', subTasks: [], isOpen: true },
},
};
addTask: (state, action) => {
const { selectedTaskId, nextTaskId } = state;
const { payload: newTaskTitle } = action;
const typed = (newTaskTitle !== '');
if (!typed) {
return;
}
state.nextTaskId = nextTaskId + 1;
state.remainingTasks[selectedTaskId].subTasks.unshift(nextTaskId);
const newTask = { title: newTaskTitle, subTasks: [], isOpen: true };
state.remainingTasks[nextTaskId] = newTask;
}
Clojure(script)
(def oldState
(atom
{:selectedTaskId :0
:nextTaskId :2
:remainingTasks {:0 {:title "root" :subTasks [:1] :isOpen true}
:1 {:title "task1" :subTasks [] :isOpen true}}}))
(defn updateId
[updator id]
(-> id
name
Integer/parseInt
updator
str
keyword))
(defn addTask
[newTaskTitle]
(let [{selectedTaskId :selectedTaskId
nextTaskId :nextTaskId}
@oldState]
(when-not (= newTaskTitle "")
(swap! oldState update-in [:nextTaskId] #(updateId inc %))
(swap! oldState update-in [:remainingTasks selectedTaskId :subTasks] #(conj % nextTaskId))
(swap! oldState update-in [:remainingTasks] #(assoc % nextTaskId {:title newTaskTitle :subTasks [] :isOpen true})))))
매크로를 이용하면 swap! 부분을 아래와 같이 간단하게 바꿀 수 있다. 이것은 함수를 정의한 것과 다르다. 새로운 문법을 만들어낸 것이다.
(defmacro updateState
[state & args]
`(do ~(for [reducer (partition 2 args)]
`(swap! ~state update-in ~@reducer))))
(when-not (= newTaskTitle "")
(updateState
oldState
[:nextTaskId] #(updateId inc %)
[:remainingTasks] #(assoc % nextTaskId {:title newTaskTitle :subTasks [] :isOpen true})
[:remainingTasks selectedTaskId :subTasks] #(conj % nextTaskId)))