객체 내부에서 createAction 을 즉시실행 함수로 주었을 때 인자를 매개변수로 받지 못하는 현상

Felix Yi·2020년 3월 17일
0

상황과 필요

이전 글에서 정석을 안 쓰고 변석을 써서 해결을 했다고 생각한 문제에서 다시 문제가 나왔다. 이벤트 인자를 받지 못하는 현상이 발생한 것이다. 디버깅이 필요했다.

const DOCUMENT = 'todos/';
const actions = {
    CHANGE_INPUT: `${DOCUMENT}CHANGE_INPUT`,
    changeInput: () => createAction(actions.CHANGE_INPUT, input => input)(),
}

최종해결

게터를 쓰면, 된다.

const DOCUMENT = 'todos/';
const actions = {
    CHANGE_INPUT: `${DOCUMENT}CHANGE_INPUT`,
    get changeInput() {
        return createAction(actions.CHANGE_INPUT, input => input)
    },
}

필요 채움

현상파악

디버그

  1. 호출이 되는 순서대로 input 을 추적했다.
  2. 액션까지는 input 이 보이지만, 리듀서 내부에서 input 이 undefined.
  3. input 이 없는 액션 객체만 계속 인서트됨
  4. createAction(액션타입, 인자처리함수)()에서 인자처리함수가 작동하지 않는 것 같다는 추론.

궁리

왜 인자를 못 받을까? 아! 즉시실행 함수라서 매번 생성되면서 인자를 받는 게 아니구나.

리덕스의 액션 객체가 아니라는 오류만 회피하려고 즉시실행으로 객체를 주었던 게 문제였다.

그럼, 객체를 주는데 그걸 어떻게 함수처럼 매번 실행할까? 허 참.

필요파악

상황파악

createAction 을 리턴하면 정상적인 액션 객체가 아니라는 오류를 준다. createAction 은 다음과 같은 리턴 타입을 가진다.

createAction(...매개변수): ActionFunction1<Arg1, Action<Payload>

ActionFunction1 은.. 옛날에 스칼라에서나 보던 타입 alias 시스템이 여기 들어와 있다. 자바에다가 함수형 집어넣으려고 등장했던 시스템인데 허허허...

ActionFunction1
Alias for:
(t1: T1) => R
Expanded:
{(t1: T1): R}

여튼, T1 타입을 받아서 R 타입을 리턴하는 함수타입.

필요궁리

지금 상황이 필요로 하는 건 다음과 같다.

actions.changeInput 을 넘기면, 처음에는 함수가 아니라고 착각을 하다가 막상 호출해서 사용하면 createAction()이 실행되어서 액션 객체를 반환.

더 구체적으로.
1. actions.changeInput 는 함수로 인식 안되어야(typeof actions.changeInput !== function) 한다.
2. 그러나 changeInput 을 호출하면 내부에 createAction()이 실행후 결과를 리턴해야 한다.
3. 한 번이 아닌 매 호출마다 매번 계산되어야한다.

아 뭔가 매번 지연된 평가가 되면서 함수라고 인식안되는데 작동은 함수처럼 하는 것. 스칼라의 lazy 키워드가 생각이 나네. vue.jsconputed(getter) 도 떠오른다.

적용

검색

google('es6 lazy evaluation')

https://stackoverflow.com/questions/24434852/how-can-i-lazy-evaluate-fields-on-a-javascript-object

테스트

  1. actions.changeInput 는 함수로 인식 안되어야(typeof actions.changeInput !== function) 한다.
console.log(typeof actions.changeInput(input))
> object
  1. 그러나 changeInput 을 호출하면 내부에 createAction()이 실행후 결과를 리턴해야 한다.
console.log(actions.changeInput(input)) 
> {
	type: "todos/CHANGE_INPUT"
	payload: "ㅇ"
}
  1. 한 번이 아닌 매 호출마다 매번 계산되어야한다. => getter 의 특성임.
profile
다른 누구와도 같은 시장 육체 노동자

0개의 댓글