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














댓글 ( 4)
댓글 남기기