Redux (생활코딩)

김지원·2020년 11월 3일
0

React

목록 보기
8/31

Redux: a predictable state container for javascript apps

  1. 복잡성을 낮춘다.
  2. 외부로부터 데이터를 차단시킨다.

cf ) !tab VScode에서 html 자동완성

리덕스 지도


store: 정보가 저장되는 곳
render: 현재 state를 반영한 ui를 만든다.
reducer: 리듀서를 이용해 state 값을 변경한다.

Redux를 사용하기

  1. store 만든다. (자동으로 state라고 하는게 생긴다.)
  2. reducer라는 함수를 만들어서 store에 주입해준다.
function reducer(state, action) {
            if(state === undefined){
                //최조의 초기화 단게 (초기 state)
                return {color:'yellow'}
            }

        }
         var store = Redux.createStore(reducer);
         console.log(store.getState());

        function red(){
            var state = store.getState();
            document.querySelector('#red').innerHTML= `
            <div class="container" id="component_red" style="background-color:${state.color}">

state 값 변경시키기

  1. state를 바꾸기 위해서는 action이라는 것을 만들어야함
  2. actiondispatch에게 제출하면 dispatchreducer를 호출
  3. 그때 이전의 state 값과 action의 값을 동시에 준다.
  4. reducer 함수가 그것을 분석해서 state에 최종적인 값을 return 해준다.

reducer가 하는 일: store에 state 값을 변경해준다!
이전의 state와 action을 받아서 다음의 state 값을 return 그 return 된 값이 새로운 state가 된다!

dispatch에 의해서 action이 들어오게 되면 reducer가 그 액션값과 기존에 있던 state 값을 참조해서 새로운 state 값을 리턴해준다.

function reducer(state, action) {
            console.log(state,action);
             /*{color: "yellow"} {type: "CHANGE_COLOR", color: "red"}*/
            if(state === undefined){
                //최조의 초기화 단게 (초기 state)
                return {color:'yellow'}
            }
            //state 복제해서 사용하기
            var newState;
            if(action.type === 'CHANGE_COLOR'){
                newState = Object.assign({}, state, {color: action.color});
                
            }
            return newState;

        }

state의 변화에 따라 UI 반영하기

store의 subscribe에다가 red를 넣어준다.
store.subscribe(red);
그러면 state 값이 바뀔때 마다 red 함수가 호출된다.

...
<input type="button" value="fire" onclick="
                store.dispatch({type:'CHANGE_COLOR', color:'red'});
            ">
            </div>
            `;
 }
        store.subscribe(red);

Reducer를 사용하니 서로 각자의 일만 알고 있으면 됨!

function red(){
            var state = store.getState();
            document.querySelector('#red').innerHTML= `
            <div class="container" id="component_red" style="background-color:${state.color}">
            <h1>red</h1>
            <input type="button" value="fire">
            </div>
            `;
        }
        store.subscribe(red);

        red();

Redux 선물: 시간여행과 로깅

redux dev tools: redux에서 store에게 전달된 action들을 버전 관리 하는 것

reducer를 통해 return 하는 값은 불변해야한다.
= 원본에 대해서 변경하면 안된다.

이러한 독립성 때문에 시간여행이 가능해졌다.

Redux 실습

action의 필수적인 프로퍼티는 type

<a onclick="
                    event.preventDefault();
                    var action = {type:'SELECT', id:${state.contents[i].id}
                    store.dispatch(action);

dispatch로 action 정보 넘어감
sotre는 reducer를 호출

TOC에 있는 목록을 눌렀을 때 그에 해당하는 내용을 article에 출려하고 싶다.
state가 바뀔때 자동으로 article 함수를 호출시키면 되지않을까?
store.subscribe(article);

최종 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
</head>
<body>
    <div id="subject"></div>
    <div id="toc"></div>
    <div id="control"></div>
    <div id="content"></div>
    <script>
        function subject(){
            document.querySelector('#subject').innerHTML =`
            <header>
                <h1>WEB</h1>
                 Hello, WEB!
            </header>
            `
        }
        function TOC(){
            var state = store.getState();
            var i =0;
            var liTags = '';
            while(i<state.contents.length){
                liTags+= `
                <li>
                  <atoken interpolation">${state.contents[i].id}}
                    store.dispatch(action);
                  " href="${state.contents[i].id}">
                    ${state.contents[i].title}
                  </a>
                </li>`;
                i+=1;
            }
            document.querySelector('#toc').innerHTML=`
            <nav>
             <ol>
            ${liTags}
             </ol>
            </nav>
             `
        }
        function control(){
            document.querySelector('#control').innerHTML=`
            <ul>
            <li><a href="/create">create</a></li>
            <li><input type="button" value="delete"></li>
        </ul>
        `
        }
        function article(){
            var state = store.getState();

            if(state.mode === 'create'){
            document.querySelector('#content').innerHTML=`
            <article>
             <form>
                <p>
                   <input type="text" name="title" placeholder="title">
                </p>
                <p>
                   <textarea name="desc" placeholder="description"></textarea>
                </p>
                <p>
                   <input type="submit">
                </p>
            </form>
            </article>
               `
            }else if(state.mode === 'read'){
            var i = 0;
            var aTitle, aDesc;
            while(i < state.contents.length){
                if(state.contents[i].id === state.selected_id){
                    aTitle = state.contents[i].title;
                    aDesc = state.contents[i].desc;
                    break;
                }
                i=i+1;
            }
            document.querySelector('#content').innerHTML=`
            <article>
             <h2>${aTitle}</h2>
             ${aDesc}
            </article>
               `
            }
            else if(state.mode === 'welcome'){
            document.querySelector('#content').innerHTML=`
            <article>
             <h2>welcome</h2>
             hello redux
            </article>
               `
            }
            
        }
        function reducer(state,action){
            if(state === undefined){
                return{
                    max_id:2,
                    mode:'create',
                    selected_id:1,
                    contents:[
                        {id:1, title:"HTML", desc:'HTML is ...'},
                        {id:2, title:"CSS", desc:"CSS is ..."}
                    ]
                }
            }
            var newState={};
            if(action.type === 'SELECT'){
                newState = Object.assign({},state,{selected_id:action.id, mode:'read'} );
            } 
            else if(action.type === 'CREATE'){
                var newMaxId = state.max_id + 1;
                var newContents = state.contents.concat();
                newContents.push({id:newMaxId, title:action.title, desc:action.desc});

                var newState=Object.assign({}, state, {
                    max_id:newMaxId,
                    contents:newContents,
                    selected_id:newMaxId,
                    mode:'read'
                })
            }
            else if(action.type === 'DELETE'){
                var newContents = [];
                var i =0;
                while(i<state.contents.length){
                    if(state.selected_id !== state.contents[i].id){
                        newContents.push(
                            state.contents[i]
                        );
                    }
                    i+=1;
                }
                newState = Object.assign({},state, {
                    contents:newContents,
                    mode:'welcome'
                })
            }
            else if(action.type === 'CHANGE_MODE') {
                newState = Object.assign({}, state, {
                    mode:action.mode
                })
            }           console.log(action, state,newState);
            return newState;
        }
        var store = Redux.createStore(reducer);
        store.subscribe(article);
        store.subscribe(TOC);
        subject();
        TOC();
        control();
        article();
    </script>
    
</body>
</html>

0개의 댓글

관련 채용 정보