안녕하세요 미루고 미루고 미루다 ( 끝 없는 배포의 연장으로 진행이 안된 상태로 이렇게 시간이... ㅜ )
최근 다시 데드라인이 다가오고 있기 때문에 급하게 관련 작업들을 진행을 하고 있습니다.
사실 FE쪽 디자인은 Antd를 사용하였는데 해당 포스팅은 다음 포스팅에 하도록 하고 ( 사용이 어렵지 않기 때문 )
Redux를 통한 전역 상태 관리에 대해서 우선 작성하게 되었습니다. Redux와 Hooks를 너무 오랜만에 사용하다보니
기억이 너무 가물가물 했기 때문입니다
1차적으로는 모두의 룰인 Counter 입니다. Counter 작성 후 개발중인 페이지의 전역 상태 관리로 바로 넘어가겠습니다.
Store
React-Redux와 관련 @types 및 Redux의 내용들은 많은 검색을 통해 알수 있기 때문에 과감하게 생략 하겠습니다. 사용성 및 작성 순서대로만
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import App from './App';
import rootReducer from './redux';
const store = createStore(rootReducer);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
1차적으로 react-redux의 Provider를 받아와서 App 을 통해 전달 합니다.
* 한 개의 프로젝트는 단 하나의 스토어만 가질수 있으며 스토어 안에는 애플리케이션의 현재 상태 및 리듀서가 있습니다.
Store에 있는 상태값을 가져와서 사용하는 컴포넌트라면 아래의 순서를 거치게 됩니다.
컴포넌트 ( 1. 스토어를 통해 상태 값을 받아옴 )
컴포넌트 ( 2. 받아온 상태값으로 렌더 )
컴포넌트 ( 3. 상태 변경을 위해서 액션 디스패치 -> 스토어가 변경됨 )
컴포넌트 ( 4. 스토어의 상태가 변경되면서 다시 컴포넌트를 재 렌더링 )
액션 : 상태 변화시 발생하는 것
액션 생성 : 액션을 만들어서 상태 변화시 사용
리듀서 : 변화를 일으킴 액션을 파라미터로 받아서 새로운 상태를 만든 후 반환
디스패치 : 액션을 발생 시킴 디스패치가 호출시 스토어가 리듀서 함수를 실행시켜서 새로운 상태를 만듬
여러가지의 상태를 사용하기 위해서는 리듀서를 여러개 사용하여야 하기 때문에 Combine 함수를 통해 rootReducer를 만든 후 해당 리듀서를 Store 에 전달합니다.
( rootReducer )
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
});
export default rootReducer;
( CounterReducer )
const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASAE';
interface counterAction {
type:string;
}
export const increase = () =>({type:INCREASE});
export const decrease = () =>({type:DECREASE});
const initialState = {
number : 55
}
function counter(state = initialState,action:counterAction){
switch(action.type){
case INCREASE:
return{
number:state.number + 1
};
case DECREASE:
return{
number:state.number -1
};
default:
return state;
}
}
export default counter;
( App 에서 hooks를 통해 state를 selector )
import React from 'react';
import './App.css';
import ReduxComponent from './ReduxComponent'
import { useSelector } from 'react-redux';
import { increase, decrease } from './redux/counter';
function App() {
const number = useSelector((state:any) => state.counter.number);
return (
<div className="App">
Test App
<ReduxComponent number={number}></ReduxComponent>
</div>
);
}
export default App;
( ReduxComponent )
import React from 'react';
const ReduxComponent:React.FunctionComponent<any> = ({number,onIncrease,onDecrease}) => {
return (
<div>
<h1>{number}</h1>
<div>
<button onClick={onIncrease} >+1</button>
<button onClick={onDecrease} >-1</button>
</div>
</div>
);
}
export default ReduxComponent;
결과
이제 동작하기 위한 Dispatch
import React from 'react';
import './App.css';
import ReduxComponent from './ReduxComponent'
import { useSelector , useDispatch } from 'react-redux';
import { increase, decrease } from './redux/counter';
function App() {
const number = useSelector((state:any) => state.counter.number);
const dispatch = useDispatch();
return (
<div className="App">
Test App
<ReduxComponent number={number}
onIncrease={()=> dispatch(increase)}
onDecrease={()=> dispatch(decrease)}
></ReduxComponent>
</div>
);
}
export default App;
실행결과
Error: Actions must be plain objects. Instead, the actual type was: 'function'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions.
액션은 plain object 여야 한다 -> increase, decrease 액션 디버깅
딱 봐도 객체가 아니라 함수로 리턴 되는 것 처럼 보이네요
onIncrease={()=> dispatch(increase())}
onDecrease={()=> dispatch(decrease())}
오타였네요 여기서 실행했어야;
수정하니 정상적으로 잘되네용 ~ hooks 기억 되살리기 끝 다음 포스팅에 작업중인 자동화 플랫폼에 적용 하도록 하겠습니다.