이 문제에 대한 쉬운 해결책은 handleClick 함수에 if 문을 추가하고 tooManyClicks가 true면 toggle을 호출하지 않는다. 하지만 이 예제의 목적을 유지하자.
제어의 역전을 위해 useToggle hook을 변경해보는건 어떨까?
API를 먼저 생각해보자. 그리고나서 구현하자.
사용자라면 state update 될 때마다 hooks을 통해 그것이 실제로 일어나기 전에 수정해보자. like so:
function Toggle() {
const [clicksSinceReset, setClicksSinceReset] = React.useState(0);
const tooManyClicks = clicksSinceReset >= 4;
const { on, toggle, setOn, setOff } = useToggle({
modifyStateChange(currentState, changes) {
if (tooManyClicks) {
// other changes are fine, but on needs to be unchanged
return { ...changes, on: currentState.on };
} else {
// the changes are fine
return changes;
}
}
});
function handleClick() {
toggle();
setClicksSinceReset(count => count + 1);
}
return (
<div>
<button onClick={setOff}>Switch Off</button>
<button onClick={setOn}>Switch On</button>
<Switch on={on} onClick={handleClick} />
{tooManyClicks ? (
<button onClick={() => setClicksSinceReset(0)}>Reset</button>
) : null}
</div>
);
}
좋아졌다.(사람들이 "switch off" or "Switch on" 버튼을 클릭할 때 일어나는 변화를 막는 거 빼고는..)
<Switch/>가 상태 토글하는 것을 막는 걸 구현해보자.
modifyStateChange가 reducer가 호출하도록 바꾸는 건 어떨까? 그리고 2번째 인자로 action을 받자.
action은 무슨 변경 타입이 일어나는지 결정하는 type을 가진다.
const { on, toggle, setOn, setOff } = useToggle({
reducer(currentState, action) {
if (tooManyClicks && action.type === "TOGGLE") {
// other changes are fine, but on needs to be unchanged
return { ...action.changes, on: currentState.on };
} else {
// the changes are fine
return action.changes;
}
}
});
control의 종류를 부여했다. TOGGLE type을 스트링으로 사용하지 말자. 대신에 참조값으로 변경하자. 이거는 typo를 피하고 editor 자동완성을 개선시켜준다.
reducer(currentState, action) {
if (tooManyClicks && action.type === useToggle.types.toggle) {
// other changes are fine, but on needs to be unchanged
return {...action.changes, on: currentState.on}
} else {
// the changes are fine
return action.changes
}
},
Well remember that the developer needs to know what our changes will be, so we'll definitely need to determine those changes first. Let's make an inline reducer:
개발자는 무엇이 변경되는지 알아야 하기 떄문에, 우리가 먼저 그 변경들을 결정할 필요가 있다는 것을 기억하자.