Redux는 application 전체의 상태(state)관리하기 위한 library이다.
React는 부모 컴포넌트에서 자식 컴포넌트에 props로 data나 state 변화를 넘겨주기 쉬운데 멀리멀리 돌아서 state값을 바꿔줘야 하고 그게 페이지도 많고 규모가 점점 커진다면 관리하기도, 개발하기도 복잡해진다.
그 복잡함을 store라는 곳에서 state를 관리함으로써 편하게 만들어준다.
Create React App (CRA)에서 개발을 했기 때문에 나는 react-redux를 사용하였다. react-redux은 redux를 react에서 사용하기 좋도록 만들어진 것이다.
원래 state의 변화를 감지하거나, action을 발행하려면 store.dispatch(), store.subscribe() 등의 메서드를 매번 사용해야 하는데, react-redux로 component에서 store를 쉽게 읽고, action을 쉽게 dispatch할 수 있도록 해준다.
이를 사용하기 위해서 우리는 redux도 설치해야 하고 react-redux도 설치해야 하는데 한번에 설치할 수도 있다.
npm install --save redux react-redux
redux는 createStore라는 함수로 store를 생성한다.
보통 store는 app에 오직 하나만 있다. 이 유일한 store에서 app 전체의 상태를 관리한다.
store 파일을 따로 만들어줘도 되지만 나는 store의 createStore은 index파일에서 해줬다.
redux의 createStore함수에 reducer를 인자로 주어야 한다. combineReducer를 해줄 rootReducer를 인자로 넣기로했다.
react app에서 store를 사용하려면 <Provider>
를 사용해야 한다. 가장 최상위 컴포넌트를 Provider로 래핑하고 속성에 store를 전달한다.
이렇게 하면 파일마다 store를 import해주지 않아도 전역으로 쓰일 수 있어서 편리하다.
Action은 사용자의 입력이나 UI 조작, 웹 요청 완료같이 어떠한 상태 변화를 일으킬 수 있는 현상이다. 즉, 어떤 조작인지 정보를 갖고 있는 자바스크립트 객체이다. 조작 정보는 type 프로퍼티에 지정한다.
action 객체를 return 해주는 액션 생성 함수는 이렇게 생겼다.
보통 action은 객체 리터럴로 바로 정의하는 것이 아니라 Action Creator(액션 생성자) 함수(여기서는 songList 함수 )로 action을 생성한다. 동일한 구조의 action 객체를 만들기 위함이다. Action Creator로 만들지 않으면 action 객체 구조가 일정하지 않을 수도 있기 때문이다.
그리고 여기에서 주의해야 할 점!!!
띄어쓰기 때문에 에러가 날 수도 있다. ( item 이 아닌 (item으로 적는 것을 추천.
store를 생성하려면 reducer가 필요하다.
reducer는 store가 가지고 있는 state를 변화시키기 위한 함수이다. reducer는 이전의 state와 action을 인자로 받고, 이 action의 내용(type)에 따라 state를 변화시킨다.
일단 reducer를 정의해보자. 아래는 songList이라는 reducer를 정의한 것이다.
그리고 위에 기존 state에 담겨있을 initialState를 적어준다. 이름은 마음대로 적어도 된다. function songList의 인자에서 state= 내가 정한 이름 을 해주면 된다.
각 action type 별로 새로운(next) state를 생성하여 return하면 된다.
ADD_MUSIC 이라는 action type과, REMOVE_MUSIC 이라는 action 등 type에 따라 return하는 state가 다르다. ADD_MUSIC은 테마에 담긴 음악을 재생목록에 추가해주는 역할을 하고 지우는 것은 삭제 버튼을 누르면 한개가 삭제되게 하는 것이다.
내 코드에는 state의 초기상태가 있었지만 state초기상태가 없다면 state를 null로 지정해주면 된다.
combineReducers 헬퍼 함수는 서로 다른 리듀싱 함수들을 값으로 가지는 객체를 받아서 createStore에 넘길 수 있는 하나의 리듀싱 함수로 바꿔준다.
생성된 리듀서는 내부의 모든 리듀서들을 호출하고 결과를 모아서 하나의 상태 객체로 바꿔준다. 상태 객체의 형태는 reducers로 전달된 키들을 따른다.
하지만 내가 실제로 사용했던 리덕스는 리듀서 함수가 하나였기에 이렇게 작성했다.
RootReducer
connect에서는 ()() 이렇게 소괄호가 두번 들어가는데 이 의미는
connect()라는 함수가 return이 되고 그 값에 또 ()함수를 돌려서 나온 값을 export하겠다는 것이다.
근데 그 값이 wrapping된 값이 나올 것이라는 의미이다.
다른 예제로 connect역할을 슬쩍 보자면,,
react-redux를 쓰지 않았을 때 사용됐을 색칠된 부분을 connect()()가 마법을 부려서 해준다!
connect의 첫 번째 소괄호에서 인자 2개가 올 수 있는데 첫 번째 인자로 mapStateToProps가 오고 두 번째 인자로는 mapDispatchToProps가 온다. 즉, connect에는 인자가 2개가 올 수 있다.
인자를 안 줄수도 있는데, 준다면
이렇게 넘긴다.
두 번째 인자가 없다면 첫 번째 인자만 써주면 되지만 첫 번째 인자는 없는데 두 번째 인자는 있다면 첫 번째에 null을 써줘야 한다. 그렇지 않으면 나는 두 번째 인자를 첫 번째 인자로 인식하기 때문이다.
함수이름은 마음대로 해도 된다.
근데 이게 redux도 props를 가지고 react도 props를 가지니까 헷갈린다.
그러니까 이름을 이해하기 쉽게 적고자 한다면
mapReduxStateToReactProps(connect의 첫 번째 인자) => Redux의 state를 react에게 props로 mapping(연결)해준다는 의미로 이름을 지어준다.
mapReduxDispatchToReactProps(connect의 두 번째 인자) => Redux의 dispatch를 react의 props로 mapping(연결)해준다는 의미로 이름을 지어준다.
이렇게 정하자.
그럼 connect를 어떻게 쓰느냐.
클릭 이벤트를 받아서 state을 바꿔줄 파일 상단부분
()=>this.getMusic(보낼 것)
이렇게 쓰도록 한다.
하단부분
상단부분
상단부분
중간 부분
하단부분
connect라는 api는 2번 호출이 되어야 하는데
첫번째 인자는 redux의 store의 state를 react의 props로 전달해주고
두번째 인자는 redux의 dispatch를 react 컴포넌트의 props로 전달해주는
역할을 우리 대신에 해준다는 것이죠.
그러나 우리가 react redux를 사용할 때 고통스러운 것은 그 마법 때문이다.
const addMusic = options => ({
type: 'ADD_MUSIC',
payload: { options }
});
addMusic({
title: '힙 터질 때',
dim: true
});
원래 action을 dispatch(발행)하고 싶다면 store.dispatch() 메서드를 사용한다. react-redux에서는 사용이 조금 다르다.
더 공부해야 할 것 2 이다.
google에 react-redux를 검색하면 공식 홈페이지가 나온다.
거기에 why use react-redux? 칸이 있는데 여기 클릭해서 밑으로 내려가면
connect.js Explained가 있다.
클릭해서 들어가면 redux를 만든 분이 react-redux의 초창기 코드가 들어있다.
다 들어있다.
내부적으로 함수값. return값이 함수값.
또 실행. component를 return 하게 되는 것이다.
인자로 전달될 때 wrappedcomponent 안에 넣어서 render가 된다.
또, unit props로 unit옮기고 했던거 마법같이 자동으로 보내준다.
그 원리는 초창기 코드에서 {...this.props}부분이다.