티스토리 뷰

자바스크립트

redux 개념 알아보기 && javascript 에서 리덕스 설치 및 이용하기

YG - 96년생 , 강아지 있음, 개발자 희망 2022. 2. 10. 12:43

Redux

리덕스는 data를 관리하는 걸 도와주는 역할을 함.

설치 방법

npm i redux

Redux Store,Reducer,getState()

Store

redux의 Store는 데이터를 저장하는 곳을 의미합니다.

 

Store을 생성하는 방법은 createStore(reducer) 입니다.

 

const countStore = createStore(countModifier);

Reducer

CreateStore는 reducer을 요구합니다.

reducer 함수를 요구하는 모습

사용방법은 const countModifier=(data=default value, action)=>{

return data

} 으로 사용할 수 있습니다. 첫번째 인자에 data 값의 default 값을 지정해주어야 합니다.

 

그렇지 않으면 undefined 가 나타납니다.

const countModifier = (count = 0) => {
  return count;
};

Reducer는 data를 수정해주는 함수로 reducer가 return 하는 것은 Store에 있는 data가 됩니다.

어떤 것도 data를 변경할 수 없습니다. 오로지 reducer로만 수정이 가능합니다.

reducer는 어떠한 값을 리턴해주는 함수 형태이어야 합니다.

 

getState()

getState()는 데이터를 불러올 수 있습니다. 사용 방법은 store.getState() 입니다.

const countModifier = (count = 0) => {
  return count;
};

const countStore = createStore(countModifier);

console.log(countStore.getState());

Redux Action,dispatch

redux의 Action은 function을 부를 때 쓰는 두 번째 parameter 혹은 argument으로 reducer와 소통하기 위한 방법입니다.

 

Reducer에게 Action을 보내는 방법은 :  store.dispatch({type:value}) 와 같이 오브젝트 형태로 보내주면 됩니다.

 

오브젝트의 key값이 되는 type 의 이름은 변경할 수 없고 고정으로 사용해야 합니다.

const countModifier = (count = 0, action) => {
  console.log(action);
  return count;
};

const countStore = createStore(countModifier);

countStore.dispatch({ type: 'Add' });

const countModifier = (count = 0, action) => {
  if (action.type === 'add') {
    return count + 1;
  } else if (action.type === 'minus') {
    return count - 1;
  } else {
    return count;
  }
};

const countStore = createStore(countModifier);

const handleAdd = () => {
  countStore.dispatch({ type: 'add' });
};
const handleMinus = () => {
  countStore.dispatch({ type: 'minus' });
};

const onChange = () => {
  console.log(countStore.getState());
};

countStore.subscribe(onChange);

add.addEventListener('click', handleAdd);
minus.addEventListener('click', handleMinus);

예시

 

 

Redux Subscribe

subscribe는 store 안에 있는 변화를 감지합니다

 

따라서 이렇게 응용할 수 있습니다.

 

const onChange = () => {
  console.log(countStore.getState());
};

countStore.subscribe(onChange);

안의 값이 변할 때 마다 콘솔을 볼 수 있고

 

const onChange = () => {
  number.innerText = countStore.getState();
};

countStore.subscribe(onChange);

데이터를 원하는 곳에 연결해서 사용할 수도 있습니다.

 

권장하는 사용 방법

Switch 사용

const countModifier = (count = 0, action) => {
  if (action.type === 'add') {
    return count + 1;
  } else if (action.type === 'minus') {
    return count - 1;
  } else {
    return count;
  }
};

reducer 역할을 하는 action 의 값으로 데이터를 수정을 할 때 if else 문보다 switch 문이 더 사용하기 편할 수 있습니다.

 

const countModifier = (count = 0, action) => {
  switch (action.type) {
    case 'add':
      return count + 1;
    case 'minus':
      return count - 1;
    default:
      return count;
  }
};

string 타입을 const 를 이용한 상수 데이터로 이용하기

const countModifier = (count = 0, action) => {
  switch (action.type) {
    case 'add':
      return count + 1;
    case 'minus':
      return count - 1;
    default:
      return count;
  }
};

const countStore = createStore(countModifier);

const handleAdd = () => {
  countStore.dispatch({ type: 'add' });
};
const handleMinus = () => {
  countStore.dispatch({ type: 'minus' });
};

'add' 혹은 'minus' 의 string으로 사용하고 있는데 사람이 하는 일이다보니 잘못입력할 수 있습니다. 

따라서 상수로 선언해주고 그 값을 이용한 것을 권장합니다.

 

const ADD = 'add';
const MINUS = 'minus';

const countModifier = (count = 0, action) => {
  switch (action.type) {
    case ADD:
      return count + 1;
    case MINUS:
      return count - 1;
    default:
      return count;
  }
};

const countStore = createStore(countModifier);

const handleAdd = () => {
  countStore.dispatch({ type: ADD });
};
const handleMinus = () => {
  countStore.dispatch({ type: MINUS });
};

 

주의 사항

data를 직접 변경하지 하지 않기

reducer에서 return을 해줄 때 return 데이터.push 혹은 데이터.pop 등 직접적으로 변경하려고 해선 안된다.

es6의 스프레드를 사용하여 [...state , {text:action.text}] 처럼 이용해야 탈이 없다.  

const reducer = (state = [], action) => {
  console.log(action);
  switch (action.type) {
    case ADD_TODO:
      return state.push(action.text);
    case DELETE_TODO:
      return [];
    default:
      return state;
  }
};

const onSubmit = (e) => {
  e.preventDefault();
  const toDo = input.value;
  input.value = '';
  store.dispatch({ type: ADD_TODO, text: toDo });
};
const reducer = (state = [], action) => {
  console.log(action);
  switch (action.type) {
    case ADD_TODO:
      return [...state, { text: action.text, id: action.id }];
    case DELETE_TODO:
      return [];
    default:
      return state;
  }
};

 

또한 리덕스 공식 문서에서는 다음과 같은 사항을 직접적으로 사용하지 말라고 합니다.

 

https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers

 

Redux Fundamentals, Part 3: State, Actions, and Reducers | Redux

The official Redux Fundamentals tutorial: learn how reducers update state in response to actions

redux.js.org

Date.now 또한 직접 사용하지 말라고 합니다.

부작용은 함수에서 값을 반환하는 것 외에 볼 수 있는 상태나 동작의 변화이다. 일반적인 부작용의 종류는 다음과 같다.

콘솔에 값 로깅
파일 저장
비동기 타이머 설정
AJAX HTTP 요청
함수 외부에 있는 일부 상태 수정 또는 함수 인수 변경
난수 또는 고유한 임의 ID 생성(예: Math.random() 또는 Date.now())

 

 

https://stackoverflow.com/questions/51867720/replace-using-date-now-inside-a-reducer

 

Replace using Date.now() inside a reducer

Documentation said i should avoid state mutation by using new Date, etc inside reducers. Help me please with advice how should it be done. Action: const RECEIVE_PRICES = 'RECEIVE_PRICES'; function

stackoverflow.com

 

따라서 action에서 값을 사용해서 reducer에서 값을 입력하는 방식으로 사용해야 할 것 같습니다.

 

 

 

Redux에서 모든 부작용(api 호출뿐만 아니라)은 Action Creators 내부에서 발생해야 합니다. 이 논리를 작업 작성기로 이동하고 호출자가 필요한 매개 변수를 전달하도록 해야 합니다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함