Store -> Container -> Component -> AsyncThunk
스토어에 있는 값을 Props와 Parameter로 넘겨받는 게 너무 불편했다.
같은 Slice 파일에 있는데 어째서!
Component가 깊어지면 깊어질수록, 공통으로 받아야할 인자가 많으면 많을수록 예쁘지 않은 코드가 나타난다.
찾아보니 CreateAsyncThunk에서 getState 옵션으로 바로 store에 접근할 수 있었다!
https://redux-toolkit.js.org/api/createAsyncThunk
async (_, { getState }) => {}
이런 식으로 처리하면 된다.
근데 이렇게 처리해도 괜찮을까? redux의 데이터 흐름을 막 쓰게 되는 거 아닐까?
이것에 대한 답변을 이 글에서 찾아보려고 한다.
2022-03-05 추가 글
TL;DR
redux제작자 Dan Abramov 는 주의해서 사용해야한다고 했음.
현재 Redux 유지 관리자 Mark Erikson은 괜찮다고함.
Dan Abramov - "thunks에서 getState
쓰지 마세요!
Dan Abramov가 2월 스택오버플로에 답했는데, 아래처럼 쓰여있었습니다.
액션 크리에이터에서 상태에 접근하는 것은 anti-pattern이고, 가능하다면 피해야합니다. 접근해도 괜찮다고 생각되는 몇가지 사례는 요청을 보내기 전에 캐시된 데이터를 확인할 때, 권한이 있는지 체크할 때입니다.
state.something.items
와 같은 데이터를 액션 크리에이터에서 전달하는 것은 명백한 anti-pattern이고 이해하기 힘든 변경 이력을 가지기 때문에 장려되지 않습니다. 만약 버그가 있고 items가 부정확하다면, 이미 액션의 일부이기 때문에 어디서 잘못된 값이 왔는지 추적하기 힘듭니다. 그러니까 주의를 가지고 사용해야합니다.
그 후로 저 코멘트에 몇몇 사람이 혼란스러워 하는 걸 봤습니다. "thunk에서 getState는 가능하지만 사실상 못쓴다면, 어떻게 해야하나요?". 지금은 "가능하다면 피해라"를 사람들이 "절대 쓰지마"로 해석하고 있지만, Dan이 스택오버플로에서 말한 사실은 사람들이 그것을 복음처럼 받아들이도록 만든다.
MarkEricson의 후반부 글.
물론, 정말 복잡한 응답 처리 로직을 가지고 있다면 중앙집중화되어야할지도 모릅니다. 하지만, 대다수의 어플리케이션은 요청하고, 액션을 디스패치하고, 완료하는 것이 간단할 것이라고 생각합니다. 중앙집중화할 것이 별로 없죠.
"단방향 데이터 흐름을 깨는 상태에 액세스"에 저는 전혀 동의하지 않습니다. 단방향 데이터 흐름의 개념은 데이터 업데이트가 한 곳에서 적용되어 시스템을 통해 전파된다는 것입니다. 일반 React 애플리케이션에서 이는 컴포넌트 트리에서 조상으로 전달하고, setState()
를 부르고 새로운 데이터를 props로 내려주는 콜백을 의미합니다. Redux 앱에서 이는 모든 "쓰기" 로직이 루트 리듀서 함수에 캡슐화 되어있고 리듀서가 디스패치된 액션에 대한 응답하고 연결된 모든 컴포넌트는 이후에 저장소에서 업데이트된 상태를 읽는다는 것을 의미합니다. 이것은 모델을 직접 수정하기 위해 양방향 입력 바인딩을 사용하는 전형적인 앵귤러 앱이나 모든 뷰가 언제든지 this.model.set("someField", someValue")
를 호출할 수 있는 Backbone 앱과 대조됩니다.
이는 양방향 입력 바인딩을 사용하여 모델을 직접 수정하는 일반적인 Angular 앱 또는 모든 보기가 this.model.set("someField", someValue)언제든지 호출할 수 있는 Backbone 앱과 대조됩니다.
내가 알기로, 썽크나 사가에서 상태를 읽어도 단방향 데이터 흐름이 중단되지 않습니다 . 액션은 여전히 디스패치되고 리듀서는 여전히 실행되며 컴포넌트는 여전히 업데이트된 상태를 읽습니다. 썽크가 상태 자체를 직접 수정하는 것과는 다릅니다. 모든 데이터 조각이 뷰에서 뷰로 명시적으로 전달되는 Elm만큼 엄격하지 않다는 점을 인정하지만 여기서는 문제가 발생하지 않습니다.