본문 바로가기
프로그래밍 개발/Redux

Redux - Redux로 간단한 웹사이트 구현하기

by Jinseok Kim 2021. 1. 23.
반응형

Redux로 간단한 웹사이트 구현하기

 

 

Redux만으로도 간단한 웹 CRUD을 구현할 수 있다.

 

 

 

 

 

1. 기본적인 HTML 뼈대 구현

<!DOCTYPE html>
<html>
    <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(){
    document.querySelector('#toc').innerHTML = `
    <nav>
        <ol>
            <li><a href="1.html">HTML</a></li>
            <li><a href="2.html">CSS</a></li>
        </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(){
    document.querySelector('#content').innerHTML = `
    <article>
        <h2>HTML</h2>
        HTML is ...
    </article>
    `
}
<!--모듈화로 부품처럼 함수로 처리하여 분리해놓고 아래에 함수를 호출하는 것을 모아놓았다.-->
subject();
TOC();
control();
article();
        </script>
        
    </body>
</html>

 

 

 

 

 

 

 

 

2. store 생성과 state 사용하기

 

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.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(){
//contents의 배열 값이 들어있는 store을 getState 메소드를 이용하여 state을 변수 선언하고 삽입
    var state = store.getState(); 
    var i = 0;
    var liTags = '';
    while(i<state.contents.length){
    //결국 가져온 contents의 배열 값을 while문을 통해 목록 링크 리스트 생성함.
        liTags = liTags + `
            <li>
                <a href="${state.contents[i].id}">${state.contents[i].title}</a>
            </li>`;
        i = 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(){
    document.querySelector('#content').innerHTML = `
    <article>
        <h2>HTML</h2>
        HTML is ...
    </article>
    `
}
function reducer(state, action){
    if(state === undefined){ //reducer 처음 초기값은 undefined이므로 if문으로 조건 삽입
        return {
        //contents 배열을 설정
            contents:[
                {id:1,title:'HTML',desc:'HTML is ..'},
                {id:2,title:'CSS', desc:'CSS is ..'}
            ]
        }
    }
}
//reducer와 연결하여 contents의 배열 값을 store 변수로 선언하여 삽입.
var store = Redux.createStore(reducer); 
subject();
TOC();
control();
article();
        </script>
        
    </body>
</html>

 

 

 

 

 

 

 

3. action을 dispatch를 통해서 전달하기

 

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.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 = liTags + `
        <li>
        // 클릭 이벤트를 주었는데 event.preventDefault();로 의도치 않은 링크를 타지 않게 하였으고
        // store.dispatch(action);을 통해 store에 타입과 id값을 담은 action 변수를 담아주었다.
            <a onclick="
                event.preventDefault();
                var action = {type:'SELECT', id:${state.contents[i].id}}
                store.dispatch(action);
            " href="${state.contents[i].id}">
                ${state.contents[i].title}
            </a>
        </li>`;
        i = 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(){
    document.querySelector('#content').innerHTML = `
    <article>
        <h2>HTML</h2>
        HTML is ...
    </article>
    `
}
function reducer(state, action){
    if(state === undefined){
        return {
        //id 식별 추가
            selcted_id:null,
            contents:[
                {id:1,title:'HTML',desc:'HTML is ..'},
                {id:2,title:'CSS', desc:'CSS is ..'}
            ]
        }
    }
    var newState;
    // action으로 들어온 타입 값이 'SELECT'이면 if문 발동
    //state에 id 식별 값 복제해주었다. 그리고 newState에 변수로 담았다.
    if(action.type === 'SELECT'){
        newState = Object.assign({}, state, {selcted_id:action.id});
    }
    
    return newState;
}
var store = Redux.createStore(reducer);
subject();
TOC();
control();
article();
        </script>
        
    </body>
</html>

 

 

 

 

 

 

 

4. subscribe를 통해서 자동 갱신 되도록 처리

 

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.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 = liTags + `
        <li>
            <a onclick="
                event.preventDefault();
                var action = {type:'SELECT', id:${state.contents[i].id}}
                store.dispatch(action);
            " href="${state.contents[i].id}">
                ${state.contents[i].title}
            </a>
        </li>`;
        i = 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(){
//store에서 .getState() 메소드를 이용하여 reducer 함수의 state 값들을 가져와서
//while문을 통해 state 값들을 id 식별자에 따라 웹 페이지에 목록의 내용을 표시하도록 하였다.
    var state = store.getState();
    var i = 0;
    var aTitle, aDesc;
    while(i < state.contents.length){
    //state 배열 id값 중 클릭 이벤트로 선택된 id 식별값이 같은 배열 값만 통과하도록 하였다.
        if(state.contents[i].id === state.selcted_id) {
            aTitle = state.contents[i].title;
            aDesc = state.contents[i].desc;
            break;
        }
        i = i + 1;
    }
    document.querySelector('#content').innerHTML = `
    <article>
        <h2>${aTitle}</h2> //id값이 같아 if문을 통과하여 담긴 변수를 html에 표시하도록 함.
        ${aDesc}           //
    </article>
    `
}
function reducer(state, action){
    if(state === undefined){
        return {
            selcted_id:2,
            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, {selcted_id:action.id});
    }
    console.log(action, state, newState);
    return newState;
}
var store = Redux.createStore(reducer);
store.subscribe(article);
subject();
TOC();
control();
article();
        </script>
        
    </body>
</html>

 

 

 

 

 

 

5. 글 생성 및 삭제 기능

 

<!DOCTYPE html>
<html>
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.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 = liTags + `
        <li>
            <a onclick="
                event.preventDefault();
                var action = {type:'SELECT', id:${state.contents[i].id}}
                store.dispatch(action);
            " href="${state.contents[i].id}">
                ${state.contents[i].title}
            </a>
        </li>`;
        i = i + 1;
    }
    document.querySelector('#toc').innerHTML = `
    <nav>
        <ol>${liTags}</ ol>
    </nav>
    `;
}
function control(){
    document.querySelector('#control').innerHTML = `
    <ul>
    //create 버튼을 클릭할때 이벤트를 설정해주었고
    //dispatch을 통해 store에 클릭 이벤트 발생 시 변화될 type과 mode을 넣어주었다.
        <li><a onclick="
            event.preventDefault();
            store.dispatch({
                type:'CHANGE_MODE',
                mode:'create'
            })
        " href="/create">create</a></li>
        
      //마찬가지로 delete 버튼에도 dispatch 메소드를 이용하여 클릭 발생시 타입을 store에 넣어줌.
        <li><input onclick="
            store.dispatch({
                type:'DELETE'
            });
        " type="button" value="delete"></li>
    </ul>
    `;
}
function article(){
    var state = store.getState();
    if(state.mode === 'create'){
        document.querySelector('#content').innerHTML = `
        <article>
        //create 버튼을 누르면 글을 생성하기 위한 구성 데이터를 보낼 폼이 등장하도록 하였다.
            <form onsubmit="
                event.preventDefault();
                var _title = this.title.value;
                var _desc = this.desc.value;
                store.dispatch({
               //폼에서 받은 value값을 담은 변수 title, desc을 dispatch을 통해 store에 담아줌.
                    type:'CREATE', 
                    title:_title,
                    desc:_desc
                })
            ">
                <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.selcted_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>
        `
        //delete 후 이동할 초기 화면으로 welcome 모드를 설정해 주었다.
    } 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, //create가 새로운 id 값을 추가하기 전에 이렇게 최대 id값을 표시해준다.
            mode:'welcome', //
            selcted_id:2,
            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, 
            {selcted_id:action.id, mode:'read'});
    } else if(action.type === 'CREATE'){
    //여기서 글이 생성된다.
        //id 값 새로 생성하여 생기는 id 값이 늘어나게하는 코드
        var newMaxId = state.max_id + 1;
        //concat 메소드를 통해 contents와 같은 배열을 복제하여 newContents에 담아줌.
        var newContents = state.contents.concat();
        //그리고 push 메소드를 통해 새로운 글을 생성하는데 필요한 글을 구성하는 근복적 코드들 삽입
        newContents.push({id:newMaxId, title:action.title, desc:action.desc});
        // assign 메소드를 통해 max_id, contents, mode을 생성한 데이터를 통해 업데이트 해줌.
        newState = Object.assign({}, state, {
            max_id:newMaxId,
            contents:newContents,
            mode:'read'
        })
        
        //action의 타입이 delete인 경우 아래 코드 발생
    } else if(action.type === 'DELETE'){
    //마찬가지로 while문을 이요하여 state의 contents 배열 값을 돌려
    //클릭 이벤트로 인하여 보내진 특정 id 식별자와 동일한 배열 값을 찾아내어 이 동일한 배열
    //값만을 newContets에 담지 않았다. 이렇게 담아지지 못한 배열 값은 삭제가 된 것이다. 
        var newContents = [];
        var i = 0;
        while(i < state.contents.length){
            if(state.selcted_id !== state.contents[i].id){
                newContents.push(
                    state.contents[i]
                );
            }
            i = i + 1;
        }
        //새로 담아진 newCotents 값을 assign 메소드를 통해 newState 변수에 담아주었고
        //mode 또한 초기화면으로 돌아가기 위해 welcome 모드로 변환해주었다.
        newState = Object.assign({},state, {
            contents:newContents,
            mode:'welcome'
        })
        //타입이 CHANGE_MODE 일때 newState에 assign을 통해 action.mode로 모드 변경해주는 것을 담음.
    } else if(action.type === 'CHANGE_MODE'){
        newState = Object.assign({}, state, {
            mode:action.mode
        });
    }
    return newState;
}
var store = Redux.createStore(reducer);
store.subscribe(article);//state 값이 바꼈을때 subscribe을 통해 바로 웹에 반응하도록 했다.
store.subscribe(TOC); //state 값이 바꼈을때 subscribe을 통해 바로 웹에 반응하도록 했다.
subject();
TOC();
control();
article();
        </script>
        
    </body>
</html>

 

 

 

 

위의 이미지에서 볼수 있듯이 간단한 CRUD을 Redux를 통해 구현할 수 있게되었다. 삭제, 생성이 되는 것을 테스트로 확인 할 수 있었다.

 

반응형

'프로그래밍 개발 > Redux' 카테고리의 다른 글

Redux - Redux 구현하기  (0) 2021.01.23
Redux - Redux란?  (0) 2021.01.23

댓글