Redux from Dan Abramov

코드위의승부사·2020년 7월 15일
0
  1. state 혹은 state tree라 부르는 한가지 객체에서 모든 변화가 일어난다.
  2. state tree 는 read-only이다. state의 변화를 위해서는 action의 dispatch가 필요하다.
  3. 순수함수인 리듀서를 사용해야 한다.

action: 앱의 state의 모든 변화가 일어나는 자바스크립트 객체

state는 앱의 데이터의 축소판, action은 그 데이터 변화의 축소판

pure functions - 함수의 리턴값이 그들의 인자값으로만 의존하는 함수이다. 네트워크나 데이터베이스 요청에 따른 부작용이 없다. 순수함수는 전달값을 수정하지 않는다.

impure functions - 순수함수와 반대로 네트워크나 데이터베이스를 요청하고 DOM을 조작하고 값을 덮어쓰고 전달함에 따라 부작용이 있을수도 있다.

리덕스에서 몇몇 함수는 순수함수여야하고 이점을 유의해야한다.

리덕스는 UI나 view layer가 앱 state가 순수함수로 이루어져있을때 가장 예측가능하다는 접근법(리액트에서 파생된)을 다른 방법으로 다룬다.
앱의 state변화를 이전 state, dispatch에 의해 실행된 action, 그리고 이후의 state 리턴하는 방식으로 해결한다.

어떤 리덕스 앱이던지 전체 앱의 state를 처리하는 하나의 특정한 함수가 있고 dispatch된 action, 앱의 다음번의 state를 갖는다. 주어진 state는 수정되지 않는다는게 중요하다.
순수해야하고 새로운 객체를 리턴해준다.

combine reducer implementing

const combineReducers = (reducers) => {
  return (state={}, action) => {
    return Object.keys(reducers).reduce(nextState, key) => {
      nextState[key] = reducers[key](state[key]), action);
      return nextState;
    },
      {}
    );
  }
};

React Todo List Example

const todo = (state, action) => {
  switch(action.type) {
    case 'ADD_TODO':
		return {
          id:action.id,
          text:action.text,
          completed:false
        };
    case 'TOGGLE_TODO':
      if(state.id !== action.id) {
        return state;
      }
      return {
        ...state,
        completed: !state.completed
      };
    default:
      return state;
  }
};

const todos = (state = [], action) => {
  switch(action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        todo(undefined, action)
        ];
    case 'TOGGLE_TODO':
      return state.map(t => todo(t, action));
    default : return state;
  }
};

const visibilityFilter = (state='SHOW_ALL', action) => {
  switch(action.type) {
    case 'SET_VISIBILITY_FILTER':
      return action.filter;
    default:
      return state;
  }
};

const {combineReducers} = Redux;
const todoApp = combineReducers({todos, visibilityFilter});
const {createStore} = Redux;
const store = createStore(todoApp);
const {Component} = React;

const FilterLink = ({filter, children }) => {
  if(filter === currentFilter){
  return <span>{children}</span>
  }
return (
  <a href ='#'
  	onClick = {e => {
  		e.preventDefault();
  		store.dispatch({type:'SET_VISIBILITY_FILTER', filter});
	}}
>
  {children}
</a>
}
/** TodoApp 내의 AddTodo를 extract
const AddTodo = ({onAddClick}) => {
  let input;
  return (
    <div>
    <input ref={node => this.input = node;} />
      <button onClick={() => {
        onAddClick(input.value)
      store.dipatch({
        type:
        'ADD_TODO',
        text:input.value,
        id:nextTodoId++;
      })
        input.value = '';
    }}>
      Add Todo
      </button>
</div>
    )
}
**/

const getVisibleTodos = (todos, filter) => {
  switch(flter) {
    case 'SHOW_ALL':
      return todos;
    case 'SHOW_COMPLETED':
      return todos.filter(t => t.completed);
    case 'SHOW_ACTIVE': 
      return todos.filter(t => !t.completed);
}

let nextTodoId = 0;
class TodoApp extends Component {
  render() {
    const {todos, visibilityFilter} = this.props;
    const visibleTodos = getVisibleTodos(todos, visibilityFilter);
    return (
      <div>
      <AddTodo onAddClick={text => 
      store.dispatch({type:'ADD_TODO', id: nextTodoId++, text}) />
/**      
	<input ref={node => this.input = node;} />
      <button onClick={() => {
      store.dipatch({
        type:
        'ADD_TODO',
        text:this.input.value,
        id:nextTodoId++;
      })
        this.input.value = '';
    }}>
      Add Todo
      </button>
**/
	<ul>{visibleTodos.map(todo => 
         <li key={todo.id}> 
	  onClick={() => {
            store.dispatch({type:'TOGGLE_TODO', id:todo.id});
            }}
         style={{textDecoration:todo.completed? 'line-through' : 'none'}}>
        {todo.text}
	</li>
	)}
   </ul>
<p>Show: 
/**
<FilterLink filter='SHOW_ALL' currentFilter={visibilityFilter}>ALL</FilterLink>
<FilterLink filter='SHOW_ACTIVE' currentFilter={visibilityFilter}>Active</FilterLink>
<FilterLink filter='SHOW_COMPLETED' currentFilter={visibilityFilter}>Completed</FilterLink>
**/
</p>
</div>

const render = () => {
	ReactDOM.render(<TodoAPP {...store.getState()}/>, document.getElmentById('root'))
}

store.subscribe(render);
render();

References

profile
함께 성장하는 개발자가 되고 싶습니다.

0개의 댓글