useReducer에서 스프레드 연산자를 무시하면 어떤 경우에 버그가 발생합니까?

Nov 25 2020

useReducer내가 본 대부분의 예에서 스프레드 연산자는 상태를 보존하는 데 사용되었습니다. 그러나 내 모든 관행에서 그것을 무시해도 문제가 발생하지 않았습니다. 감속기는 스프레드 연산자 없이도 상태 자체를 보존 할 수있는 것 같습니다. 다음 예를 확인하십시오.

const initialState = {
    color: 'black',
    bgColor: 'white'
}

const reducer = (state, action) => {
    switch (action.type) {
        case 'dawn':
            return {
                ...state,
                color: 'white',
                bgColor: 'purple'
            }
        case 'reset':
            return initialState
        default:
            return {
                state
            }
    }
}

const UseReducerColorSetter = () => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const { color, bgColor } = state;
    return (
        <>
            <div style={{ color: `${color}`, backgroundColor: `${bgColor}` }} className='card'>
                Hello
            </div>
            <button onClick={() => dispatch({ type: 'dawn' })}>Dawn mode</button>
            <button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
        </>
    )
}

이 예에서 제거해 ...state도 문제, 상태 변경, 콘솔 오류 등이 발생하지 않습니다.

이 질문에서 나는 물었다 : useReducer에서 스프레드 연산자를 사용해야합니까? 스프레드 연산자를 무시하면에서 문제가 발생 useState했지만 여전히 useReducer.

누군가가 문제를 일으키는 스프레드 연산자를 무시하는 몇 가지 예를 제공 할 수 있습니까 useReducer? 감속기가 상태를 유지할 수 있습니까?

답변

1 BrianThompson Nov 24 2020 at 23:53

다음은 감속기의 모든 객체 속성을 바꾸지 않으면 손실되는 것을 보여주는 실행 예제입니다. 콘솔에 기록 된 초기 값을 인쇄 된 결과와 비교합니다.

const initialState = {
  color: "black",
  bgColor: "white"
};

const reducer = (state, action) => {
  switch (action.type) {
    case "dawn":
      return {
        bgColor: "purple" // Updated to only return one property to illustrate the problem
      };
    case "reset":
      return initialState;
    default:
      return {
        state
      };
  }
};

function App() {
  const [state, dispatch] = React.useReducer(reducer, initialState);

  React.useEffect(() => {
    console.log("Initial: ", state)
    dispatch({ type: "dawn" });
  }, []);

  return <div>{JSON.stringify(state)}</div>;
}

ReactDOM.render(<App />, document.getElementById('root'));
<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="root"></div>

감속기 함수 의 시그니처에 주목하십시오 (state, action) => newState. 이 함수는 새로운 상태를 반환합니다. 따라서 return감속기에서 가져온 것은 전체적으로 새로운 상태 값입니다. 즉, 루트 상태 개체를 확산하지 않으면 새 개체에 명시 적으로 설정되지 않은 모든 값이 손실됩니다.

질문에 직접 답하기 위해 리듀서 업데이트에서 이전 상태를 전파하지 않으면 상태가 배열 또는 객체 일 때 버그가 발생하고 해당 구조의 모든 값을 수동으로 바꾸지 않습니다.

당신이 경우 항상 각 개체의 속성을 설정하거나 이전 상태를 반환, 당신은 버그가 발생하지 않습니다. 이것은 당신이 질문에 제시 한 시나리오이며 불필요한 것처럼 보이는 이유입니다.

SergioVargas Nov 24 2020 at 23:28

특정 경우에는 상태 값 (color 및 bgColor)을 변경하기 때문에 문제가 발생하지 않거나 영향을 미치지 않습니다. 앱이 항상 bgColor를 가질 것으로 예상하는 경우 문제가 발생할 수 있습니다.

 case 'blue':
            return {
                color: 'blue',
            }