Redux 기본학습-2
생활코딩의 리덕스 강좌를 보면서 학습한 내용 정리용.
생활코딩에서 redux를 설명해 놓은 이미지 인용.
1. 강의 1 - 정적인 버전
main.html
<!DOCTYPE html>
<html>
<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><input type="button" value="delete"></li>
</ul>
<h2>HTML</h2>
HTML is ...
</article>
</body>
</html>
2. 강의 2 - 부품화
main.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>
`;
}
// TOC 는 Table of content. 목록이란 뜻.
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 atricle() {
document.querySelector('#content').innerHTML = `
<article>
<h2>HTML</h2>
HTML is ...
</article>
`;
}
subject();
TOC();
control();
atricle();
</script>
</body>
</html>
3. 강의 3 - store & state
main.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/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>
`;
}
// TOC 는 Table of content. 목록이란 뜻.
function TOC(){
var state = store.getState();
var i = 0;
var liTags = '';
while(i<state.contents.length){
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 atricle() {
document.querySelector('#content').innerHTML = `
<article>
<h2>HTML</h2>
HTML is ...
</article>
`;
}
function reducer(state, actoin){
// 초기값
if(state === undefined){
return {
contents : [
{id:1, title:'HTML', desc:'HTML is ..'},
{id:2, title:'CSS', desc:'CSS is ..'}]
}
}
return ;
}
var store = Redux.createStore(reducer);
subject();
TOC();
control();
atricle();
</script>
</body>
</html>
4. 강의 4 - dispatch와 action
main.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/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>
`;
}
// TOC 는 Table of content. 목록이란 뜻.
function TOC(){
var state = store.getState();
var i = 0;
var liTags = '';
while(i<state.contents.length){
// event.preventDefault(); -> 이벤트가 발생했을때
// 그 이벤트를 발생시킨 태그의 기본 동작을 무효화.
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>ddddd
`;
}
function control(){
document.querySelector('#control').innerHTML = `
<ul>
<li><a href="/create">create</a></li>
<li><input type="button" value="delete"></li>
</ul>
`;
}
function atricle() {
document.querySelector('#content').innerHTML = `
<article>
<h2>HTML</h2>
HTML is ...
</article>
`;
}
function reducer(state, action){
console.log(state, action);
// 초기값
if(state === undefined){
return {
// selected_id:null,
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});
}
console.log(action, state, newState);
return newState;
}
var store = Redux.createStore(reducer);
subject();
TOC();
control();
atricle();
</script>
</body>
</html>
5. 강의 5 - subscribe
main.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/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>
`;
}
// TOC 는 Table of content. 목록이란 뜻.
function TOC(){
var state = store.getState();
var i = 0;
var liTags = '';
while(i<state.contents.length){
// event.preventDefault(); -> 이벤트가 발생했을때
// 그 이벤트를 발생시킨 태그의 기본 동작을 무효화.
// li 안의 a 태그를 클릭할 때 마다 store.dispatch(action); 를 갱신하도록 함.
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>ddddd
`;
}
function control(){
document.querySelector('#control').innerHTML = `
<ul>
<li><a href="/create">create</a></li>
<li><input type="button" value="delete"></li>
</ul>
`;
}
function atricle() {
var state = store.getState();
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>
`;
}
function reducer(state, action){
console.log(state, action);
// 초기값
if(state === undefined){
return {
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});
}
console.log(action, state, newState);
return newState;
}
var store = Redux.createStore(reducer);
store.subscribe(atricle);
subject();
TOC();
control();
atricle();
</script>
</body>
</html>
6. 강의 6 - 글생성 구현
main.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/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>
`;
}
// TOC 는 Table of content. 목록이란 뜻.
function TOC(){
var state = store.getState();
var i = 0;
var liTags = '';
while(i<state.contents.length){
// event.preventDefault(); -> 이벤트가 발생했을때
// 그 이벤트를 발생시킨 태그의 기본 동작을 무효화.
// li 안의 a 태그를 클릭할 때 마다 store.dispatch(action); 를 갱신하도록 함.
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>ddddd
`;
}
function control(){
document.querySelector('#control').innerHTML = `
<ul>
<li><a onclick="
event.preventDefault();
" href="/create">create</a></li>
<li><input type="button" value="delete"></li>
</ul>
`;
}
function atricle() {
var state = store.getState();
if(state.mode === 'create') {
document.querySelector('#content').innerHTML = `
<article>
<form onsubmit="
event.preventDefault();
var title = this.title.value;
var 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'){
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>
`;
}
}
function reducer(state, action){
console.log(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});
} else if(action.type === 'CREATE'){
// 배열을 복제할때는 concat() 을 쓰면 편하게 복제 가능
// 아무런 인자를 주지 않으면 똑같은데 새로운 배열을 리턴한다.
var newContents = state.contents.concat();
// 새로 추가할 요소의 id를 max_id + 1 로 만든다.
var newMaxId = state.max_id + 1;
newContents.push({ id:newMaxId, title:action.title, desc:action.desc });
newState = Object.assign({}, state, {
max_id:newMaxId,
contents:newContents,
mode:'read'
})
}
console.log(action, state, newState);
return newState;
}
var store = Redux.createStore(reducer);
store.subscribe(atricle);
store.subscribe(TOC);// state가 바뀔때 변화를 인지해서 새로 화면을 그리는 함수는 몇개를 선언하든 상관없음.
subject();
TOC();
control();
atricle();
</script>
</body>
</html>
7. 강의 7 - 글 삭제 구현
Redux를 이용하면 지금 짜고 있는 부품에만 집중하면 되고 그 부품이 어떤 액션이 일어났을때 store 에 action 을 잘 전달하는 일만 하면 되고 상태가 바뀌었을때 자기에게 맞는 모양으로 자신을 바꾸어 주는 것에만 집중하면 된다.
즉 내가 A라는 부품을 만들고 있을때는 A라는 부품에만 집중해 주면 되기 때문에 다른 부품에는 신경쓸 필요가 없다.
main.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/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>
`;
}
// TOC 는 Table of content. 목록이란 뜻.
function TOC(){
var state = store.getState();
var i = 0;
var liTags = '';
while(i<state.contents.length){
// event.preventDefault(); -> 이벤트가 발생했을때
// 그 이벤트를 발생시킨 태그의 기본 동작을 무효화.
// li 안의 a 태그를 클릭할 때 마다 store.dispatch(action); 를 갱신하도록 함.
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>ddddd
`;
}
function control(){
document.querySelector('#control').innerHTML = `
<ul>
<li><a onclick="
event.preventDefault();
store.dispatch({
type:'CHANGE_MODE',
mode:'create'
});
" href="/create">create</a></li>
<li><input onclick="
store.dispatch({
type:'DELETE'
});
" type="button" value="delete"></li>
</ul>
`;
}
function atricle() {
var state = store.getState();
if(state.mode === 'create') {
document.querySelector('#content').innerHTML = `
<article>
<form onsubmit="
event.preventDefault();
var title = this.title.value;
var 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'){
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){
console.log(state, action);
// 초기값
if(state === undefined){
return {
max_id:2, // 현재 요소 갯수
mode:'welcome',
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'){
// 배열을 복제할때는 concat() 을 쓰면 편하게 복제 가능
// 아무런 인자를 주지 않으면 똑같은데 새로운 배열을 리턴한다.
var newContents = state.contents.concat();
// 새로 추가할 요소의 id를 max_id + 1 로 만든다.
var newMaxId = state.max_id + 1;
newContents.push({ id:newMaxId, title:action.title, desc:action.desc });
newState = Object.assign({}, state, {
max_id:newMaxId,
contents:newContents,
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 = 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(atricle);
store.subscribe(TOC);// state가 바뀔때 변화를 인지해서 새로 화면을 그리는 함수는 몇개를 선언하든 상관없음.
subject();
TOC();
control();
atricle();
</script>
</body>
</html>
https://redux.js.org/introduction/ecosystem 을 참고해서 기존에 있는 Redux 의 플러그인을 설치해서 사용하면 좀더 편하게 개발할 수 있다고 함.
이어서 불변이라는 개념(Immutability) 도 공부하면 좋다는듯. Reducer 를 이해할때 도움이 됨.
참고 사이트 : https://lunit.gitbook.io/redux-in-korean/introduction/ecosystem