Redux: a predictable state container for javascript apps
cf ) !tab
VScode에서 html 자동완성
store: 정보가 저장되는 곳
render: 현재 state를 반영한 ui를 만든다.
reducer: 리듀서를 이용해 state 값을 변경한다.
function reducer(state, action) {
if(state === undefined){
//최조의 초기화 단게 (초기 state)
return {color:'yellow'}
}
}
var store = Redux.createStore(reducer);
console.log(store.getState());
function red(){
var state = store.getState();
document.querySelector('#red').innerHTML= `
<div class="container" id="component_red" style="background-color:${state.color}">
action
이라는 것을 만들어야함action
을 dispatch
에게 제출하면 dispatch
가 reducer
를 호출reducer
함수가 그것을 분석해서 state
에 최종적인 값을 return 해준다.
reducer
가 하는 일: store에 state 값을 변경해준다!
이전의 state와 action을 받아서 다음의 state 값을 return 그 return 된 값이 새로운 state가 된다!
dispatch에 의해서 action이 들어오게 되면 reducer가 그 액션값과 기존에 있던 state 값을 참조해서 새로운 state 값을 리턴해준다.
function reducer(state, action) {
console.log(state,action);
/*{color: "yellow"} {type: "CHANGE_COLOR", color: "red"}*/
if(state === undefined){
//최조의 초기화 단게 (초기 state)
return {color:'yellow'}
}
//state 복제해서 사용하기
var newState;
if(action.type === 'CHANGE_COLOR'){
newState = Object.assign({}, state, {color: action.color});
}
return newState;
}
store의 subscribe에다가 red를 넣어준다.
store.subscribe(red);
그러면 state 값이 바뀔때 마다 red 함수가 호출된다.
...
<input type="button" value="fire" onclick="
store.dispatch({type:'CHANGE_COLOR', color:'red'});
">
</div>
`;
}
store.subscribe(red);
function red(){
var state = store.getState();
document.querySelector('#red').innerHTML= `
<div class="container" id="component_red" style="background-color:${state.color}">
<h1>red</h1>
<input type="button" value="fire">
</div>
`;
}
store.subscribe(red);
red();
redux dev tools
: redux에서 store에게 전달된 action들을 버전 관리 하는 것
reducer를 통해 return 하는 값은 불변해야한다.
= 원본에 대해서 변경하면 안된다.
이러한 독립성 때문에 시간여행이 가능해졌다.
action
의 필수적인 프로퍼티는 type
<a onclick="
event.preventDefault();
var action = {type:'SELECT', id:${state.contents[i].id}
store.dispatch(action);
dispatch로 action 정보 넘어감
sotre는 reducer를 호출
TOC에 있는 목록을 눌렀을 때 그에 해당하는 내용을 article에 출려하고 싶다.
state가 바뀔때 자동으로 article 함수를 호출시키면 되지않을까?
store.subscribe(article);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
</head>
<body>
<div id="subject"></div>
<div id="toc"></div>
<div id="control"></div>
<div id="content"></div>
<script>
function subject(){
document.querySelector('#subject').innerHTML =`
<header>
<h1>WEB</h1>
Hello, WEB!
</header>
`
}
function TOC(){
var state = store.getState();
var i =0;
var liTags = '';
while(i<state.contents.length){
liTags+= `
<li>
<atoken interpolation">${state.contents[i].id}}
store.dispatch(action);
" href="${state.contents[i].id}">
${state.contents[i].title}
</a>
</li>`;
i+=1;
}
document.querySelector('#toc').innerHTML=`
<nav>
<ol>
${liTags}
</ol>
</nav>
`
}
function control(){
document.querySelector('#control').innerHTML=`
<ul>
<li><a href="/create">create</a></li>
<li><input type="button" value="delete"></li>
</ul>
`
}
function article(){
var state = store.getState();
if(state.mode === 'create'){
document.querySelector('#content').innerHTML=`
<article>
<form>
<p>
<input type="text" name="title" placeholder="title">
</p>
<p>
<textarea name="desc" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
</article>
`
}else if(state.mode === 'read'){
var i = 0;
var aTitle, aDesc;
while(i < state.contents.length){
if(state.contents[i].id === state.selected_id){
aTitle = state.contents[i].title;
aDesc = state.contents[i].desc;
break;
}
i=i+1;
}
document.querySelector('#content').innerHTML=`
<article>
<h2>${aTitle}</h2>
${aDesc}
</article>
`
}
else if(state.mode === 'welcome'){
document.querySelector('#content').innerHTML=`
<article>
<h2>welcome</h2>
hello redux
</article>
`
}
}
function reducer(state,action){
if(state === undefined){
return{
max_id:2,
mode:'create',
selected_id:1,
contents:[
{id:1, title:"HTML", desc:'HTML is ...'},
{id:2, title:"CSS", desc:"CSS is ..."}
]
}
}
var newState={};
if(action.type === 'SELECT'){
newState = Object.assign({},state,{selected_id:action.id, mode:'read'} );
}
else if(action.type === 'CREATE'){
var newMaxId = state.max_id + 1;
var newContents = state.contents.concat();
newContents.push({id:newMaxId, title:action.title, desc:action.desc});
var newState=Object.assign({}, state, {
max_id:newMaxId,
contents:newContents,
selected_id:newMaxId,
mode:'read'
})
}
else if(action.type === 'DELETE'){
var newContents = [];
var i =0;
while(i<state.contents.length){
if(state.selected_id !== state.contents[i].id){
newContents.push(
state.contents[i]
);
}
i+=1;
}
newState = Object.assign({},state, {
contents:newContents,
mode:'welcome'
})
}
else if(action.type === 'CHANGE_MODE') {
newState = Object.assign({}, state, {
mode:action.mode
})
} console.log(action, state,newState);
return newState;
}
var store = Redux.createStore(reducer);
store.subscribe(article);
store.subscribe(TOC);
subject();
TOC();
control();
article();
</script>
</body>
</html>