현재 프로젝트의 기술 스택은 https://github.com/wnsdudSoftkim/Tech_Blog 에서 확인 할 수 있습니다.
Redux란 무엇일까요? 상태관리는 뭐고 local state , global state는 무엇이길래 React와 Redux를 엮어 쓰는 걸까요. 저번 CodeEditor.js 에서 보았듯 데이터를 하위에서 상위로 이동시켜주어야 합니다. 여기서 말하는 하위는 CodeEditor.js 이고 상위는 부모격인 AddPost.js가 되겠죠?
Redux 란 쉽게 말해보면 저장소 같은 느낌입니다. component 끼리 관리하던 local state를 store에 저장시켜 원하는 곳에서 불러올 수 있는 것이죠. 예를들어 이 프로젝트에선 하위에서 상위로 데이터를 보내는 것이 아닌 store 로 데이터를 저장하고 상위에서 불러오는 방식이 되겠습니다.
그러면 일단 store에 저장해달라는 명령을 하고 , store은 그 명령을 수행하겠죠. 또, 쓰는 곳에서 데이터를 보내달라는 명령을 하고 , store은 그 명령을 수행하는 식으로 이해하면 되겠습니다. 그 명령을 해주는 Hook은 useSelector와 useDispatch 입니다.
useDispatch는 store에 저장하는 명령, useSelector은 store에서 데이터를 가져오는 명령. 바로 사용해 볼까요? 먼저 react-redux 를 설치해 줍니다.
npm i react-redux
여기서 잠깐, 명령을 받는 Redux의 코드도 짜야겠죠? 여기서도 쉽게 2가지를 풀어 설명하겠습니다. action 과 reducer 두가지로 나뉘어서 코드를 짭니다.
action은 내가 할 행동을 알려주는 것이고 reducer은 그 action의 행동에 따라 상태가 바뀌게 됩니다. 이렇게 상태관리가 되는 것입니다.
action/index.js 에 행동을 알려주는 코드를 작성해 봅니다.
export const EDIT_BODY = "EDIT_BODY"
export const EditBody = (cursor,body,thumbnail) => {
return {
type:"EDIT_BODY",
data:{
cursor:cursor,
body:body,
thumbnail:thumbnail
}
}
}
reducers/getPost.js에서 액션함수를 불러와 내가 작업 할 코드를 작성해줍니다.
import {FETCH_GET_POST} from '../action/index'
function data(state={}, action) {
switch(action.type) {
case FETCH_GET_POST:
return {
...action.payload,
}
default:
return state
}
}
export default data
reducers/index.js 에서 루트 리듀서로 컴바인하는 작업을 해줍니다. 이해안되도 일단 넘어가 줍니다.
import {combineReducers} from 'redux'
import fetchGetPost from './getpost'
const rootReducer = combineReducers({
fetchGetPost,
})
export default rootReducer
여기까지 하고 src단의 index.js 에서 마무리 작업만 하면 끝납니다. 하지만 그 전에 다시 설명하자면 useDispatch는 데이터를 store에 저장하는 역활이라고 했었습니다.
그 역활은 reducers/getPost.js가 맡고 있습니다. useDispatch를 통해 전달된 명령은 getPost.js 의 data함수로 들어와서 FETCH_GET_POST 케이스를 작동시킵니다.
이 케이스는 action/index.js 에서 가져온 함수이죠. 그렇게 케이스를 작동시키면 , 원하는 데이터가 store에 저장된 것을 확인 할 수 있습니다. redux-devTools를 활용하면 더 쉽게 활용이 가능합니다. 마지막으로 src/Index.js에서 작업을 해야합니다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import rootReducer from './store/reducers'
import reportWebVitals from './reportWebVitals';
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducer, composeEnhancer(applyMiddleware(thunk)))
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
여기까지 했으면 , 앱 하나에 store 하나를 가지고 있는 겁니다. 그 store은 많은 store들이 combine 된 것일 수도 있겠죠. 결국 store에서 데이터를 불러오는 useSelector은 여기에 접근하게 해주는 Hook 인겁니다.
CodeEditor.js
const state ={
cursor:"",
body:"",
thumbnail:[],
}
const dispatch = useDispatch()
dispatch(EditBody(state.cursor,state.body,state.thumbnail[0]))
AddPost.js
const mydata = useSelector(state=> state.fetchgetPost)