useReducer에서 스프레드 연산자를 사용해야합니까?

Nov 20 2020

편집 : Brian의 답변을 확인한 후 두 번째 예제에서도 제거 ...state하면 첫 번째 예제와 동일한 동작이 발생 하므로이 질문이 잘못되었다는 것을 알았습니다 . 무엇이 잘못된 행동을 보 였는지 잘 모르겠으며 불편을 끼쳐 드려 죄송합니다. Brian의 대답은 사용에 대한 좋은 설명입니다.

다음 두 코드 스 니펫을 비교 initialState하면 하나는 사용 useState하고 다른 하나는 사용하는 것을 제외하고 두 상태를으로 한 번에 업데이트하여 동일한 작업을 수행 합니다 useReducer.

  1. useState

const {useState} = React;

const initialState = {
  name: 'John',
  age: 20
};

const Example = () => {
  const [state, setState] = useState(initialState);

  const handleName = () => {
    setState({...state, name: 'Tom'});
  }
  
  const handleAge = () => {
    setState({...state, age: 30});
  }

  return (
    <div>
      <p>{state.name}</p>
      <p>{state.age}</p>
      <button onClick={handleName}>
        Click to change name
      </button>
      <button onClick={handleAge}>
        Click to change age
       </button>
    </div>
  );
};

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

  1. useReducer

const {useReducer} = React;

const initialState = {
    name: 'Tom',
    age: 30
}
const reducer = (state, action) => {
    switch (action.type) {
        case 'name':
            return {
                ...state,
                name: 'John'
            }
        case 'age':
            return {
                ...state,
                age: 25
            }
        default:
            return state
    }
}

const Example = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
    return (
        <div>
            <p>Name: {state.name}</p>
            <p>Age: {state.age}</p>
            <button onClick={() => dispatch({ type: 'name' })}>Click to update name</button>
            <button onClick={() => dispatch({ type: 'age' })}>Click to update age</button>
        </div>
    )
};

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

...state첫 번째 예에서 제거 하면 상태를 단일 키 / 값 쌍으로 설정하므로 더 이상 작동하지 않습니다. 두 번째 예에서도 같은 일이 일어날 것으로 예상했지만 그렇지 않았습니다. 두 번째 예제는 스프레드 연산자를 제거한 상태에서 잘 작동합니다.

두 번째 예에 대해 세 가지 질문이 있습니다.

  1. 스프레드 연산자의 용도는 무엇입니까?
  2. 스프레드 연산자를 제거한 후에도 여전히 작동하는 이유는 무엇입니까?
  3. 스프레드 연산자없이 잘 작동한다면 두 번째 예에서 스프레드 연산자가 필요하지 않다는 의미입니까?

답변

1 BrianThompson Nov 24 2020 at 17:17

나는이에 매우 유사한 질문을 이해 이 하나 , 그러나 나는 희망 잘못된 정보를 얻기에서 미래의 리더를 방지하기 위해 어쨌든 답을주고있다.

어느 쪽 useStateuseReducer무엇이든지 이전 값의 병합을하지 않는다. 이전 상태 값의 유지는 상태 업데이트 ( setState호출 또는 리듀서 함수 정의) 중 사용자의 책임 입니다.

아래의 수정 된 코드에서 이것을 분명히 볼 수 있습니다. 내가 변경 한 것은 ...state각 스위치 케이스에서 제거하는 것입니다.

const {useReducer} = React;

const initialState = {
    name: 'Tom',
    age: 30
}
const reducer = (state, action) => {
    switch (action.type) {
        case 'name':
            return {
                name: 'John'
            }
        case 'age':
            return {
                age: 25
            }
        default:
            return state
    }
}

const Example = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
    return (
        <div>
            <p>Name: {state.name}</p>
            <p>Age: {state.age}</p>
            <button onClick={() => dispatch({ type: 'name' })}>Click to update name</button>
            <button onClick={() => dispatch({ type: 'age' })}>Click to update age</button>
        </div>
    )
};

ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

이 목적을 위해 스프레드 연산자가 자주 사용되는 이유는 변경되지 않은 모든 값을 새 개체에 넣는 가장 지루한 방법이기 때문입니다.