git clone https://github.com/reactjs/redux
cd redux/examples/counter
npm install
npm start
리액트 설치했으면 소스 폴더 다운받아서 돌리기만 하면 됨
Redux 인강:
Part 1: Getting Started with Redux (30 free videos)
Part 2: Building React Applications with Idiomatic Redux (27 free videos)
리덕스를 사용하면, 모든 state를 (간단하든 복잡하든) 하나의 거대한 JavaScript 객체로 표현하게 됨
간단한 카운터 -> 숫자 하나
여러개의 간단한 카운터 -> 숫자의 list
ex) todoApp -> todos와 visibilityFilter를 필드로 가지는 객체
todos: todo의 리스트 (각 todo는 id, text, completed를 필드로 가지는 객체)
visibilityFilter: SHOW_ALL or SHOW_COMPLETED or SHOW_ACTIVE
First Principle of Redux: 애플리케이션에서 내에서 발생하는 모든 변화는 state(or statetree)라고 불리는 하나의 JavaScript 객체를 통해 관리된다
Second Principle of Redux: Statetree는 Read-Only이며, 마음대로 수정할 수 없다. State를 수정하려면 action을 dispatch해야 한다
action은 state의 change를 나타내는 JavaScript 객체임
각 action 객체는 type 필드를 필수로 가짐(일반적으로 String 타입)
todoList에서 todo를 하나 추가할 때마다,
Component는 특정 id와 text와 type을 필드로 갖는 action을 dispatch하는 일을 수행함.
Component가 action을 dispatch 한다!
Pure function: 인풋 인자에 아무 짓도 안함
Impure function: 인풋 인자에 뭔 짓을 함
Redux의 함수들은 Pure해야 한다!
Third Principle of Redux:
reducer는 previous state와 dispatched action을 받아서 next state를 도출하는 함수. Pure function이기 때문에 인풋으로 받는 객체를 수정하는게 아니라 새로운 객체를 만들어서 리턴함.
//가장 기본적인 형태
function counter(state, action){
if(typeof state === 'undefined'){
return 0;
}
//이상한 state를 받으면 initial 값을 리턴
if(action.type === 'INCREMENT'){
return state + 1;
} else if(action.type === 'DECREMENT'){
return state - 1;
} else{
return state;
}
}
/*undefined state이 들어오는 case
=> 인풋 argument에 default 인자를 줌으로써 해결*/
function counter(state = 0, action){
if(action.type === 'INCREMENT'){
return state + 1;
} else if(action.type === 'DECREMENT'){
return state - 1;
} else{
return state;
}
//함수 내부는 switch문을 쓰면 더 깔끔함
}
//이렇게 바꿔줄 수도 있음
const counter = (state = 0, action) => {
if(action.type === 'INCREMENT'){
return state + 1;
} else if(action.type === 'DECREMENT'){
return state - 1;
} else{
return state;
}
//함수 내부는 switch문을 쓰면 더 깔끔함
}import { createStore } from 'redux';
// const { createStore } = Redux;
// var createStore = Redux.createStore;
// 다 똑같음
const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
const store = createStore(counter);
console.log(store.getState());
store.dispatch({ type: 'INCREMENT' })
console.log(store.getState());
store.subscribe(())import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
const Counter = ({ value, onIncrement, onDecrement }) => (
<div>
<h1>{value}</h1>
<button onClick={onIncrement}>+</button>
<button onClick={onDecrement}>-</button>
</div>
)
const store = createStore(counter);
const render = () => {
ReactDOM.render (
<Counter
value={store.getState()}
onIncrement={()=>store.dispatch({type:'INCREMENT'})}
onDecrement={()=>store.dispatch({type:'DECREMENT'})}
/>,
document.getElementById('root')
)
}
render()
store.subscribe(render)