velopert / react-tutorial

벨로퍼트와 함께하는 모던 리액트 튜토리얼 문서
https://react.vlpt.us/
347 stars 100 forks source link

20. useReducer 를 사용하여 상태 업데이트 로직 분리하기 · GitBook #4

Open utterances-bot opened 5 years ago

utterances-bot commented 5 years ago

20. useReducer 를 사용하여 상태 업데이트 로직 분리하기 · GitBook

undefined

https://react.vlpt.us/basic/20-useReducer.html

kevinJuni commented 5 years ago

action.type를 읽을수 없다고 뜨는데 이유가뭘까요..?

jsh3658 commented 4 years ago

CREATE_USER 시에는 CHANGE_INPUT처럼 spread연산자로 input값 가지고 오지 않고, 왜 inputs: initialState.inputs에 넣어주는 건가요?

console.log찍어보니까 state.inputs안에 값이 들어가져 있던데, ...state로 값을 가지고 오는것 아닌가요?

case 'CREATE_USER':
 return {
    ...state,
   users: {
      ...state.users,
      users
   }
}

이렇게 코딩 하면 안되는 건가요 ㅠㅠ? 제가 이해한 바로는 spread연산자로 initialState의 object를 모두 가져와서 users를 overwrite해서 리스트에 추가한다로 감을 잡고 있는데, 설명 부탁드립니다

dextto commented 4 years ago

onCreate를 다시 구현할 때 const { name, value } = e.target; 하는 부분을 빼먹으셨네요.

abys7free commented 3 years ago

안녕하세요 좋은 강의 감사드립니다~

제가 놓친 부분이 있어서 질문드립니다.

아래 코드에서 action.name을 []로 감싸서 [action.name]으로 쓰는 이유가 뭔가요? 어떻게 검색해봐야하는지라도 알려주시면 감사하겠습니다.

function reducer(state, action) {
  switch (action.type) {
    case 'CHANGE_INPUT':
      return {
        ...state,
        inputs: {
          ...state.inputs,
          [action.name]: action.value
        }
      };
    default:
      return state;
  }
}

감사합니다.

abys7free commented 3 years ago

Computed property names 라는 것이군요. 찾았습니다. 예전에 얘기해주신거 같기도 한데 가물가물했습니다.

참고: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer

https://stackoverflow.com/questions/6500573/dynamic-keys-for-object-literals-in-javascript

Swacker3927 commented 3 years ago

concat 함수로 항목 추가하는 방법 외에도 spread 연산자로 항목 추가하는 방법이 있나요?

Conradmaker commented 3 years ago

concat 함수로 항목 추가하는 방법 외에도 spread 연산자로 항목 추가하는 방법이 있나요?

case CREATE_USER:
return {
inputs: initialState.inputs,
users: [...state.users, action.user] //state.users 가장 뒤에 추가
};
Harry1757 commented 3 years ago

@jsh3658 안에 인풋창을 초기화한상태로 다시보여주기 위함인 것 같습니다

Harry1757 commented 3 years ago

@abys7free dispatch 부분에서 구조분해할당한 name 을 보내고 있는데 CreateUser 보시면 name="username" 혹은 name="email" 으로 되어있어서 이름에따른 value 를 받아오려고 하는것 같습니다!!

ohiomanbo commented 3 years ago

제가 아직 완전히 이해를 하지 못한건지, switch 속 ...state가 어떤 역할인지 애매합니다 ㅠㅠ

ohiomanbo commented 3 years ago

@abys7free 님이 설명해주신 'spread연산자로 initialState의 object를 모두 가져와서 users를 overwrite해서 리스트에 추가한다'로 이해하면 될까요 ?

ohiomanbo commented 3 years ago

앗 @jsh3658 님이군요 잘못된 언급 죄송합니다!

wenodev commented 3 years ago

useReducer

useReducer 형태

  const [state, dispatch] = useReducer(reducer, initialState);
jody96 commented 3 years ago

감사합니다!!

BorisPark commented 3 years ago

추가적인 팁을 적어놓자면, reducer 함수에서도 똑같이 비구조화 할당을 할 수 있습니다. 위 코드에서는 state가 내부의 inputs와 users의 구조로 불변하기 때문에 이 부분에 대해서


const { users, inputs } = state;
const { name, value, user, id } = action;

와 같은 식으로 작성한다면, state.users를 users로 축약할 수 있고 onCreate에서 username, email과 같이 따로따로 적던 부분도 ...inputs로 작성할 수 있습니다.

action 내부 param은 type에 따라서 받아오는 것이 다르므로 비구조화 할당이 안되는 거 아닌가 하실 수도 있지만, dictionary는 받아오지 않은 값을 undifined로 남겨둡니다. (https://learnjs.vlpt.us/useful/06-destructuring.html) 즉, 처리로직이 있기 때문에 문제는 되지 않습니다. (다만 같이 작업하는 사람이 어떤 param이 undifined인지 값이 할당된건지 처음 볼 때는 모를 수 있으니 팀프로젝트라면 이 부분은 주석 등으로 action마다 사용하는 param을 적어두는게 삽질 안하고 편하겠죠.)

sshusshu commented 3 years ago

useReducer : 상태 업데이트 로직 분리

useState와 다르게 컴포넌트 바깥에 작성 & 다른 파일에 작성 후 불러와서 사용

function reducer(state, action) { // 새로운 상태를 만드는 로직 // const nextState = ... return nextState; } reducer 함수 : 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환 reducer 에서 반환하는 상태는 곧 컴포넌트가 지닐 새로운 상태

action 은 업데이트를 위한 정보 type 값을 지닌 객체 형태로 사용

const [state, dispatch] = useReducer(reducer, initialState); state 는 우리가 앞으로 컴포넌트에서 사용 할 수 있는 상태 dispatch 는 액션을 발생시키는 함수

useReducer vs useState useState: 컴포넌트에서 관리하는 값이 단순, 숫자, 문자열 , boolean 값 useReducer: 컴포넌트에서 관리하는 값이 여러개가 되어서 상태의 구조가 복잡

josunyjostar commented 2 years ago

덕분에 reducer도 잘 배움 벨로퍼트 차냥해

rollrat commented 2 years ago

굳굳

proamateur92 commented 2 years ago

잘 배우고 갑니다 벨로퍼트 선생님 ^^7

donald-lendit commented 1 year ago

https://ktseo41.github.io/blog/log/avoid-these-common-pitfalls-of-react-usestate.html?utm_source=substack&utm_medium=email 를 읽다가 이 글로 흘러들어왔는데요. 이 글에

서로 의존하는 여러 상태 변수는 useState 대신 useReducer를 도입하게 되는 일반적인 시나리오입니다.

라는 문구가 있습니다. useState, useReducer 선택 시 또 하나의 기준이 될 수 있을 것 같네요. 잘 읽었습니다. 감사합니다.

KangWoosung commented 1 year ago

const [newState, dispatch] = useReducer( reducer, initState ) // reducer 는 switch 분기 펑션이다. // 새로운 상태를 리턴하지만, 코드 아무데서나 호출할 수 있는 펑션이 아니다. // useReducer 훅의 첫번째 param 으로 reducer 펑션을 전달해주면, dispatch() 에서 내부적으로 reducer() 가 호출되고, 상태변경을 완료한다. // action.object 의 데이터들을 펑션 내부에서 처리함으로써 다양한 state 변화를 reducer() 한 곳에서 일원화 관리할 수 있다. function reducer(state, action) { switch action.type { case 'INCREMENT' : return state + 1; case 'ADD_USER' : return { ...state, inputs : { ...state.inputs, [action.name] : action.value } } default return state; } } // dispatch( action ) 가 내부적으로 reducer() 펑션을 호출하고 state 변경을 완료한다. // action param 은 object 로 전달해줘야만 한다. 단일 밸류를 전달해줘야 한다면 굳이 reducer 를 사용할 필요 없다. dispatch( { type:'INCREMENT' } )