React

 

React - 생활코딩 1

 

React - 생활코딩 2

 

React - 생활코딩 3 - 클래스 방식과 함수방식 비교 및 라이프 사이클

 

 

★ React 리액트 리덕스(Redux) - 리덕스 완전정복 , 최신 리덕스 Toolkit 사용

 

 

vscode  확장 패키지 추가

1. - Auto Import - ES6, TS, JSX, TSX

2. - Reactjs code snippets

3. - ESLint

4. - Prettier - Code formatter

Visual Studio Code 폴더/파일 아이콘 변경하기

 

 

리액트  프로젝트 생성

 npx create-react-app  경로

예) npx create-react-app E:\react-app2

 

1. 오리엔테이션

1.수업소개

 

 

 

 

 

 

 

 

 

2. 리덕스 여행의 지도

 

 

2-1.소개

 

2-2.state와 render의 관계

 

 

 

 

2-2.action과 reducer

 

 

 

 

 

3.Redux가 좋은 가장 중요한 이유

 

 

 

 

크롬브라우저 확장프로그램설치 리덕스 :

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko-KR

 

 

4.Redux가 없다면

 

without-redux.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리덕스가 없다면</title>
<style>
    .container{
        border:5px solid black;
        padding:10px
    }            
</style>
</head>
<body>
    <div id="red"></div>
    <div id="green"></div>
    <div id="blue"></div>
<script>
    function red(){
        document.querySelector("#red").innerHTML=`
            <div class="container" id="component_red">
                <h1>red</h1>
                <input type="button" value="fire"  onclick="document.querySelector('#component_red').style.backgroundColor='red';
                document.querySelector('#component_green').style.backgroundColor='red' 
                 document.querySelector('#component_blue').style.backgroundColor='red'               
                ">
                
            </div>
        `;
    }
    red();
    function green(){
        document.querySelector("#green").innerHTML=`
            <div class="container" id="component_green">
                <h1>green</h1>
                <input type="button" value="fire"  onclick="
                   document.querySelector('#component_red').style.backgroundColor='green';
                   document.querySelector('#component_green').style.backgroundColor='green' ;
                    document.querySelector('#component_blue').style.backgroundColor='green'       
                ">
            </div>
        `;
    }
    green();

    function blue(){
        document.querySelector("#blue").innerHTML=`
            <div class="container" id="component_blue">
                <h1>blue</h1>
                <input type="button" value="fire"  onclick="
                   document.querySelector('#component_red').style.backgroundColor='blue';
                   document.querySelector('#component_green').style.backgroundColor='blue' ;  
                  document.querySelector('#component_blue').style.backgroundColor='blue'         
                ">
            </div>
        `;
    }
    blue();    
</script>    
</body>
</html>

 

 

 

 

 

3. Redux의 적용

 

공식 사이트 : https://redux.js.org/

 

설치방식   :  $npm install --save redux

CDN 방식 :   https://cdnjs.com/libraries/redux

 

===================== ======== 다음을 추천한다.============= ===================== 

1.   redux 설치

&  yarn add redux react-redux  redux-promise  redux-thunk

 

2. createStore  deprecate 로 인하여   React Redux Toolkit  설치

$  yarn add @reduxjs/toolkit

또는

$ npm install @reduxjs/toolkit react-redux

 

크롬브라우저 확장프로그램설치 리덕스 :

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko-KR

 

===================== ===================== ===================== 

 

 

5.1.Redux의 적용 :store 생성

 

with-redux.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리덕스 적용</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <style>
    .container{
        border:5px solid black;
        padding:10px
    }            
</style>
</head>
<body>
    <div id="red"></div>
<script>
    //은행 예시 
    //state - 은행 장부
    //reducer - 은행 장부직원
    //dispatch - 은행 창구직원
    function reducer(state, action){
        if(state===undefined){
            return {color:"yellow"}  
        }
    }

    //초기값 생성
    const store=Redux.createStore(reducer);

    function red(){

        //리덕스에서 데이터 가져오기   store.getState();
        const state=store.getState();
        console.log("getState" , state);


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

    red();  
</script>    
</body>
</html>

 

 

 

5.2.reducer와 action을 이용해서 새로운 state 값 만들기

 

 

with-redux.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리덕스 적용</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <style>
    .container{
        border:5px solid black;
        padding:10px
    }            
</style>
</head>
<body>
    <div id="red"></div>
<script>
    //은행 예시 
    //state - 은행 장부
    //reducer - 은행 장부직원
    //dispatch - 은행 창구직원
    function reducer(state, action){
        //state=>현재 store 값
        console.log(state, action);
        if(state===undefined){
            return {color:"yellow"}  
        }
        if(action.type==="CHANGE_COLOR"){
            //깊은 복사
            newState=Object.assign({}, state, {color:'red'})
        }
        return newState
    }


    //초기값 생성
    const store=Redux.createStore(reducer);

    function red(){

        //리덕스에서 데이터 가져오기   store.getState();
        const state=store.getState();
        console.log("getState" , state);


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

    red();  
</script>    
</body>
</html>

 

 

 

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

 

 

with-redux.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리덕스 적용</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <style>
    .container{
        border:5px solid black;
        padding:10px
    }            
</style>
</head>
<body>
    <div id="red"></div>
    <div id="blue"></div>
    <div id="green"></div>
<script>
    //은행 예시 
    //state - 은행 장부
    //reducer - 은행 장부직원
    //dispatch - 은행 창구직원
    function reducer(state, action){
        //state=>현재 store 값
 
        if(state===undefined){
            return {color:"yellow"}  
        }
        if(action.type==="CHANGE_COLOR"){
            //깊은 복사
            newState=Object.assign({}, state, {color:action.color})
        }
        console.log(action.type, action, state, newState);
        return newState
    }

    //초기값 생성
    const store=Redux.createStore(reducer);


    function red(){
        //리덕스에서 데이터 가져오기   store.getState();
        const 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"  onclick="store.dispatch({type:'CHANGE_COLOR', color:'red'})">                
            </div>
        `;
    }
    //subscribe 은 store 값이 변경되면 red 함수(여기서는 render()역할)가 호출되도록 한다.
    store.subscribe(red);
    red();  


   function blue(){   
        const state=store.getState();
        document.querySelector("#blue").innerHTML=`
            <div class="container" id="component_blue" style="background-color:${state.color}">
                <h1>blue</h1>
                <input type="button" value="fire"  onclick="store.dispatch({type:'CHANGE_COLOR', color:'blue'})">                
            </div>
        `;
    }
    store.subscribe(blue);
    blue();
    
    function green(){   
        const state=store.getState();
        document.querySelector("#green").innerHTML=`
            <div class="container" id="component_green" style="background-color:${state.color}">
                <h1>green</h1>
                <input type="button" value="fire"  onclick="store.dispatch({type:'CHANGE_COLOR', color:'green'})">                
            </div>
        `;
    }
    store.subscribe(green);
    green(); 
</script>    
</body>
</html>

 

 

 

6.Redux 선물: 시간여행과 로깅

 

 

 

크롬브라우저 확장프로그램설치 리덕스 :

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=ko-KR

 

 

https://github.com/reduxjs/redux-devtools

 

 

Redux DevTools Extension  : https://github.com/zalmoxisus/redux-devtools-extension

 

    //초기값 생성
    const store=Redux.createStore(reducer,
         window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );

 

 

 

소스 : https://github.com/braverokmc79/LifeCoding/commit/af0e4bc73502d41268ed12f903db351e3ecf061c

 

 

4. 실전 Redux

 

7-1.정적인 웹페이지 만들기

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>실전 Redux</title>
</head>
<body>
    <header>
        <h1>WEB</h1>
        Hello, WEB!
    </header>
    <nav>
        <ol>
            <li><a href="1.html">HTML</a></li>
            <li><a href="2.html">CSS</a></li>            
        </ol>
    </nav>
    <article>
        <ul>
            <li><a href="/create">create</a></li>
             <li><a href="/update">create</a></li>
            <li><input type="button" value="delete"></li>
        </ul>
        <h2>HTML</h2>
        HTML is ...
    </article>
</body>
</html>

 

 

 

7-2.부품화

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>실전 Redux</title>
</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(){
    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><a href="/update">update</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>

 

 

 

7-3.store 생성과 state 사용하기

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.controls.map(item=>{
        return `        
         <li><a href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a href="/create">create</a></li>
             <li><a href="/update">update</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{
            controls:[
                {id:1,title:'HTML',desc:"HTML is ..."},
                {id:2,title:'CSS', desc:"CSS is ..."},
                {id:3,title:'js', desc:"js is ..."}
            ]
        }
    }<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.controls.map(item=>{
        return `        
         <li><a href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a href="/create">create</a></li>
             <li><a href="/update">update</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{
            controls:[
                {id:1,title:'HTML',desc:"HTML is ..."},
                {id:2,title:'CSS', desc:"CSS is ..."},
                {id:3,title:'js', desc:"js is ..."}
            ]
        }
    }
    return;
}

const store=Redux.createStore(reducer);
const state=store.getState();
console.log("state ", state);


subject();
TOC();
control();
article();
        </script>
</body>
</html>
    return;
}

const store=Redux.createStore(reducer);
const state=store.getState();
console.log("state ", state);


subject();
TOC();
control();
article();
        </script>
  

</body>
</html>

 

 

 

 

 

7-4.action을 dispatch를 통해서 전달하기

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.controls.map(item=>{
        return `        
         <li><a href="#"
            onclick="event.preventDefault();            
            const action={
                type:'SELECT', 
                id:${item.id}
            }
            store.dispatch(action);
            "
            href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a href="/create">create</a></li>
             <li><a href="/update">update</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{
            selectd_id:null,
            controls:[
                {id:1,title:'HTML',desc:"HTML is ..."},
                {id:2,title:'CSS', desc:"CSS is ..."},
                {id:3,title:'js', desc:"js is ..."}
            ]
        }
    }

    let newState={};
    if(action.type==="SELECT"){
        //깊은 복사
       newState=Object.assign({}, state, {selectd_id:action.id});

    }

    console.log(action, state, newState);
}

const store=Redux.createStore(reducer);
const state=store.getState();
console.log("state ", state);


subject();
TOC();
control();
article();
        </script>
</body>
</html>

 

 

 

7-5.subscribe를 통해서 자동 갱신 되도록 처리

 

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.contents.map(item=>{
        return `        
         <li><a href="#"
            onclick="event.preventDefault();            
            const action={
                type:'SELECT', 
                id:${item.id}
            }
            store.dispatch(action);
            "
            href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a href="/create">create</a></li>
             <li><a href="/update">update</a></li>
            <li><input type="button" value="delete"></li>
        </ul>
    `;
}

function article(){
    const state=store.getState();
    console.log(" state", state);

    if(state.selectd_id!=undefined){
        const data=state.contents.filter(item=>{            
            return item.id==state.selectd_id;
        })[0]; 
        
        document.querySelector("#content").innerHTML=`
            <article>
                <h2>${data.title}</h2>
                ${data.desc}
            </article>
        `;
    }
    
 
}

function reducer(state, action){  
    if(state===undefined){
        return{
            selectd_id:2,
            contents:[
                {id:1,title:'HTML',desc:"HTML is ..."},
                {id:2,title:'CSS', desc:"CSS is ..."},
                {id:3,title:'js', desc:"js is ..."}
            ]
        }
    }

    let newState={};
    if(action.type==="SELECT"){
        //깊은 복사
       newState=Object.assign({}, state, {selectd_id:action.id});
    }

    console.log(action, state, newState);
    return newState;
}

const store=Redux.createStore(reducer);
store.subscribe(article);

subject();
TOC();
control();
article();
        </script>
        
</body>
</html>

 

 

 

7-6.글생성 기능 구현

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.contents.map(item=>{
        return `        
         <li><a href="#"
            onclick="event.preventDefault();            
            const action={
                type:'SELECT', 
                id:${item.id}
            }
            store.dispatch(action);
            "
            href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    const state=store.getState();

    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a 
                onclick="
                    event.preventDefault();
                
                "
                
                href="/create">create</a></li>
             <li><a 
                onclick="event.preventDefault();
                
                "                
                href="/update">update</a></li>
            <li><input type="button" value="delete"></li>
        </ul>
    `;
}

function article(){
    const state=store.getState();


    if(state.mode==="create"){
        document.querySelector("#content").innerHTML=`
             <article>    
                <form
                    onsubmit="
                        event.preventDefault();
                        const _title=this.title.value;
                        const _desc=this.desc.value;
                        store.dispatch({
                            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"){
        
            const data=state.contents.filter(item=>{            
                return item.id==state.selectd_id;
            })[0];             
            document.querySelector("#content").innerHTML=`
                <article>
                    <h2>${data.title}</h2>
                    ${data.desc}
                </article>
            `;
    }


}

function reducer(state, action){  
    if(state===undefined){
        return{
            max_id:3,
            mode:'create',
            selectd_id:2,
            contents:[
                {id:1,title:'HTML',desc:'HTML is ...'},
                {id:2,title:'CSS', desc:'CSS is ...'},
                {id:3,title:'js', desc:'js is ...'}
            ]
        }
    }

    let newState={};
    if(action.type==="SELECT"){
        //깊은 복사
       newState=Object.assign({}, state, {selectd_id:action.id});
    }else if(action.type==="CREATE"){
        //concat() 을 하면 복제 처리 된다.
        let newMaxId=state.max_id+1;
        let newContents=state.contents.concat();
        newContents.push({
            id:newMaxId,
            title:action.title,          
            desc:action.desc
        });

        newState=Object.assign({}, state, {
            max_id:newMaxId,
            contents:newContents,
            selectd_id:newMaxId,
            mode:'read'
        });

    }

    console.log(action, state, newState);
    return newState;
}

const store=Redux.createStore(reducer);
store.subscribe(article);
store.subscribe(TOC);

subject();
TOC();
control();
article();
        </script>
        
</body>
</html>

 

 

 

 

7-7.글삭제 기능 구현

 

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.contents.map(item=>{
        return `        
         <li><a href="#"
            onclick="event.preventDefault();            
            const action={
                type:'SELECT', 
                id:${item.id}
            }
            store.dispatch(action);
            "
            href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    const state=store.getState();

    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a 
                onclick="
                    event.preventDefault();
                    store.dispatch({
                        type:'CREATE_FORM'
                    })
                "
                
                href="/create">create</a></li>
             <li><a 
                onclick="event.preventDefault();
                    store.dispatch({
                        type:'UPDATE_FORM'
                    })
                "                
                href="/update">update</a></li>
            <li><input type="button"
                onclick="event.preventDefault();
                    store.dispatch({
                        type:'DELETE'                        
                    })
                "
                value="delete"></li>
        </ul>
    `;
}

function article(){
    const state=store.getState();


    if(state.mode==="create"){
        document.querySelector("#content").innerHTML=`
             <article>    
                <form
                    onsubmit="
                        event.preventDefault();
                        const _title=this.title.value;
                        const _desc=this.desc.value;
                        store.dispatch({
                            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"){
        
            const data=state.contents.filter(item=>{            
                return item.id==state.selectd_id;
            })[0];             
            document.querySelector("#content").innerHTML=`
                <article>
                    <h2>${data.title}</h2>
                    ${data.desc}
                </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:3,
            mode:'welcome',
            selectd_id:2,
            contents:[
                {id:1,title:'HTML',desc:'HTML is ...'},
                {id:2,title:'CSS', desc:'CSS is ...'},
                {id:3,title:'js', desc:'js is ...'}
            ]
        }
    }

    let newState={};
    if(action.type==="SELECT"){
        //깊은 복사
       newState=Object.assign({}, state, {
            mode:"read",
            selectd_id:action.id
        });

    }else if(action.type==="CREATE_FORM" ){
        state.mode="create";
        newState=Object.assign({}, state, {
            mode:"create"
        })
    }else if(action.type==="CREATE"){
        //concat() 을 하면 복제 처리 된다.
        let newMaxId=state.max_id+1;
        let newContents=state.contents.concat();
        newContents.push({
            id:newMaxId,
            title:action.title,          
            desc:action.desc
        });

        newState=Object.assign({}, state, {
            max_id:newMaxId,
            contents:newContents,
            selectd_id:newMaxId,
            mode:'read'
        });

    }else if(action.type==="DELETE"){
      
        const newContents=state.contents.filter((item)=>{
            return item.id !=state.selectd_id;
        });
        //console.log("_contents ", _contents);

        newState=Object.assign({}, state, {
            contents:newContents,
            mode:'welcome'
        });
    }

    console.log(action, state, newState);
    return newState;
}

const store=Redux.createStore(reducer);
store.subscribe(article);
store.subscribe(TOC);

subject();
TOC();
control();
article();
        </script>
        
</body>
</html>

 

 

 

 

7-7.글수정 구현

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.min.js"></script>
    <title>실전 Redux</title>
</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(){
    const state=store.getState();
    const liTags= state.contents.map(item=>{
        return `        
         <li><a href="#"
            onclick="event.preventDefault();            
            const action={
                type:'SELECT', 
                id:${item.id}
            }
            store.dispatch(action);
            "
            href="${item.id}">${item.title}</a></li>
        `;
    });

    document.querySelector("#toc").innerHTML=`
    <nav>
        <ol>
            ${liTags.join("")}     
        </ol>
    </nav>
    `;
}
function control(){
    const state=store.getState();

    document.querySelector("#control").innerHTML=`
        <ul>
            <li><a 
                onclick="
                    event.preventDefault();
                    store.dispatch({
                        type:'CREATE_FORM'
                    })
                "
                
                href="/create">create</a></li>
             <li><a 
                onclick="event.preventDefault();
                    store.dispatch({
                        type:'UPDATE_FORM'
                    })
                "                
                href="/update">update</a></li>
            <li><input type="button"
                onclick="event.preventDefault();
                    store.dispatch({
                        type:'DELETE'                        
                    })
                "
                value="delete"></li>
        </ul>
    `;
}

function article(){
    const state=store.getState();


    if(state.mode==="create"){
        document.querySelector("#content").innerHTML=`
             <article>    
                <form
                    onsubmit="
                        event.preventDefault();
                        const _title=this.title.value;
                        const _desc=this.desc.value;
                        store.dispatch({
                            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"){
        
            const data=state.contents.filter(item=>{            
                return item.id==state.selectd_id;
            })[0];             
            document.querySelector("#content").innerHTML=`
                <article>
                    <h2>${data.title}</h2>
                    ${data.desc}
                </article>
            `;


    }else if(state.mode=="welcome"){
           document.querySelector("#content").innerHTML=`
                <article>
                    <h2>Welcome</h2>
                    Hello, Redux!!!
                </article>
            `;

     }else if(state.mode=="update"){
            const state=store.getState();
            const data=state.contents.filter((item)=>{
                return item.id===state.selectd_id;
            })[0];
            console.log("data ", data);

            document.querySelector("#content").innerHTML=`
             <article>    
                <form
                    onsubmit="
                        event.preventDefault();
                        const _title=this.title.value;
                        const _desc=this.desc.value;
                        store.dispatch({
                            type:'UPDATE',
                            title:_title,
                            desc:_desc
                        })
                    "
                >
                    <p>
                        <input type="text" name="title" placeholder="title"
                            value="${data.title}"
                        >
                    </p> 
                    <p>
                      <textarea name="desc" placeholder="description" >${data.desc}</textarea>
                    </p> 
                    <p>
                        <input type="submit">
                    </p>   
                </form>    
            </article>
        `;
    }


}

function reducer(state, action){  
    if(state===undefined){
        return{
            max_id:3,
            mode:'welcome',
            selectd_id:2,
            contents:[
                {id:1,title:'HTML',desc:'HTML is ...'},
                {id:2,title:'CSS', desc:'CSS is ...'},
                {id:3,title:'js', desc:'js is ...'}
            ]
        }
    }

    let newState={};
    if(action.type==="SELECT"){
        //깊은 복사
       newState=Object.assign({}, state, {
            mode:"read",
            selectd_id:action.id
        });

    }else if(action.type==="CREATE_FORM" ){
        newState=Object.assign({}, state, {
            mode:"create"
        })
    }else if(action.type==="CREATE"){
        //concat() 을 하면 복제 처리 된다.
        let newMaxId=state.max_id+1;
        let newContents=state.contents.concat();
        newContents.push({
            id:newMaxId,
            title:action.title,          
            desc:action.desc
        });

        newState=Object.assign({}, state, {
            max_id:newMaxId,
            contents:newContents,
            selectd_id:newMaxId,
            mode:'read'
        });

    }else if(action.type==="DELETE"){
      
        const newContents=state.contents.filter((item)=>{
            return item.id !=state.selectd_id;
        });
        //console.log("_contents ", _contents);

        newState=Object.assign({}, state, {
            contents:newContents,
            mode:'welcome'
        });
    }else if(action.type==="UPDATE_FORM" ){
        newState=Object.assign({}, state, {
            mode:"update"
        })
    }else if(action.type==="UPDATE"){
        console.log("UPDATE DATA : ", action);

        const newContents=state.contents.map(item=>{
            if(item.id===state.selectd_id){
               const data={                
                    id:state.selectd_id,
                    title:action.title,
                    desc:action.desc
                };
               return data;                
            }else{
                return item;
            }
        });

        newState=Object.assign({}, state, {
            contents:newContents,
            mode:'read',            
        });
        
    }

    console.log(action, state, newState);
    return newState;
}

const store=Redux.createStore(reducer);
store.subscribe(article);
store.subscribe(TOC);

subject();
TOC();
control();
article();
        </script>
        
</body>
</html>

 

 

 

 

 

 

 

 

 

5. 마무리

 

 

 

 

 

 

 

 

 

소스 : https://github.com/braverokmc79/LifeCoding

 

 

 

 

 

 

 

react

 

about author

PHRASE

Level 60  라이트

곡기(穀氣)가 원기(元氣)를 이기면 살이 찌개 되며 장수하지 못한다. 이와 반대로 원기가 곡기를 이기면 살은 찌지 않고 장수한다. -동의보감

댓글 ( 4)

댓글 남기기

작성