안녕하세요!

FE 개발자 유진주입니다.

Web/React

[처음 만난 리덕스] 4. Action

ypearl 2023. 12. 25. 04:14

Action

: Redux Store에 저장된 데이터(State)에 변화를 주기 위한 행동

 

*Redux ActionJavaScript 객체 형태로 존재

(일반 JS 객체와 다른 점은, type이라는 필드를 무조건 포함한다는 점!

type - Redux Action의 type을 의미.)

 

{
    type: 'ADD_TODO',  // type: Action의 이름(개발자가 정의)
    text: 'Redux 공부하기'  // (payload): Action을 처리하는 데 필요한 부가 데이터
}

 

 

Action Creator

: Action 객체를 생성하는 역할을 하는 JavaScript 함수

 

function addTodo(text) {
	return { // 여기서 리턴하는 객체가 바로 Redux Action 객체
    	type: 'ADD_TODO',
        text: text
    };
}

 

Action Creator와 Action의 관계

 

 

[실습] TODO 애플리케이션에 다양한 Action 정의하기 / Creator 만들기

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>처음 만난 리덕스 - TODO</title>
</head>
<body>
    <h3>오늘 할 일</h3>
    <ul id="todo-list"></ul>

    <div>
        <input id="input-text"/>
        <button id="add-button">할 일 추가</button>
        <button id="remove-button">할 일 삭제</button>
        <button id="remove-all-button">모두 삭제</button>
        <button id="logging-state">State Logging</button>
    </div>

    <script>
        // 액션 타입을 별도로 선언해 코드의 반복을 줄임
        var ACTION_TYPE_ADD_TODO = "ADD_TODO";
        var ACTION_TYPE_REMOVE_TODO = "REMOVE_TODO";
        var ACTION_TYPE_REMOVE_ALL = "REMOVE_ALL";

        function todoReducer(state, action){
            switch(action.type){
                case ACTION_TYPE_ADD_TODO:
                    return state.concat(action.text);
                case ACTION_TYPE_REMOVE_TODO:
                    return state.slice(0, -1); // slice 함수를 사용해 배열의 마지막 아이템 하나를 삭제
                case ACTION_TYPE_REMOVE_ALL:
                    return [];
                default:
                    return state;
            }
        }

        function loggerMiddleware({getState}){ // 구조분해할당: 파라미터 중 getState만 꺼내서 사용
            return (next) => (action) => {
                console.log("dispatch 예정 action", action);

                // Middleware chain에 있는 다음 dispatch 함수를 호출
                const returnValue = next(action);

                console.log("dispatch 이후 state", getState());

                return returnValue;
            };
        }

        var store = Redux.createStore(
            todoReducer,
            ["처음 만난 리덕스 공부하기"],
            Redux.applyMiddleware(loggerMiddleware)
        );

        var todoListElem = document.getElementById("todo-list");
        var inputElem = document.getElementById("input-text");

        function render() {
            // 이전 TODO 목록 초기화 (아이템이 중복으로 쌓이지 않기 위함)
            todoListElem.innerHTML="";

            // TODO 목록 렌더링
            store.getState().forEach((todo) => { // getState 함수: store에서 현재 state 가져옴
                // 반복문 사용해 아이템의 개수만큼 li 태그 만들어 ul 태그에 append
                const todoListItemElem = document.createElement("li");
                todoListItemElem.textContent=todo;
                todoListElem.appendChild(todoListItemElem);
            });
        }

        render();
        store.subscribe(render); // Redux Store의 state가 변경될 때마다 render 함수 호출

        function addTodoActionCreator(text){
            return {
                type: ACTION_TYPE_ADD_TODO,
                text: text,
            };
        }

        function removeTodoActionCreator(){
            return {
                type: ACTION_TYPE_REMOVE_TODO,
            };
        }

        function removeAllActionCreator(text){
            return {
                type: ACTION_TYPE_REMOVE_ALL,
            };
        }

        document
            .getElementById("add-button")
            .addEventListener("click", function(){
                // Action을 실제로 dispatch
                store.dispatch(addTodoActionCreator(inputElem.value));

                // Input 초기화
                inputElem.value = "";
            });
       
        document
            .getElementById("remove-button")
            .addEventListener("click", function(){
                store.dispatch(removeTodoActionCreator());
            });

        document
            .getElementById("remove-all-button")
            .addEventListener("click", function(){
                store.dispatch(removeAllActionCreator());
            });
        document
            .getElementById("logging-state")
            .addEventListener("click", function(){
                console.log("현재 state", store.getState());
            });
    </script>
</body>
</html>

 

 

 

실행 결과