toggle switch를 만들던 중에 클릭을 해도 코드가 정상 동작하지 않는다!
// src/store/ThemeContext.js
// ...생략...
export const ThemeContext = createContext();
export const ThemeProviderWrapper = ({ children }) => {
const [theme, setTheme] = useState("light");
const toggleTheme = (newTheme) => {
console.log("🔄 toggleTheme 테마:", theme);
setTheme(newTheme);
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<ThemeProvider theme={theme === "light" ? lightTheme : darkTheme}>
{children}
</ThemeProvider>
</ThemeContext.Provider>
);
};
// src/components/ThemeToggleSwitch.jsx
// ...생략...
const ThemeToggleSwitch = () => {
const { theme, toggleTheme } = useContext(ThemeContext);
const handleToggle = () => {
console.log("🔄 handleToggle 테마:", theme);
toggleTheme(theme === "light" ? "dark" : "light");
};
return (
<>
<ToggleSwitch
checked={theme !== "light"}
onChange={handleToggle}
/>
</>
);
};
export default ThemeToggleSwitch;
// src/components/buttons/ToggleSwitch.jsx
// ...생략...
const ToggleSwitch = ({ checked, onChange }) => (
<SwitchContainer checked={checked} onClick={onChange} >
<HiddenCheckbox
type="checkbox"
checked={checked}
readOnly
/>
<SwitchCircle checked={checked} />
</SwitchContainer>
);
export default ToggleSwitch;
toggle switch를 클릭하면 dark mode로 변하지 않고 콘솔도 생각과 다르게 두 번씩 찍힌다.
코드를 보면 SwitchContainer 자체에도 onClick이 걸려 있어서 이벤트가 전파(propagation)되면서 추가적인 상태 변경이 발생할 수 있다.
즉, 클릭 이벤트가 부모(SwitchContainer)까지 전파되고 있다는 것이다.
ToggleSwitch에 Event.preventDefault()를 사용할 수 있도록 코드를 수정했다.
// 생략
const ToggleSwitch = ({ checked, onChange }) => {
const handleClick = (e) => {
e.preventDefault(); // ✅ 클릭 이벤트 전파 방지
console.log("🟡 ToggleSwitch 클릭됨! 현재 checked 값:", checked);
onChange(!checked); // ✅ checked 값을 반전하여 전달
};
return (
<SwitchContainer checked={checked} onClick={handleClick}>
<HiddenCheckbox
type="checkbox"
checked={checked}
readOnly
/>
<SwitchCircle checked={checked} />
</SwitchContainer>
);
};
export default ToggleSwitch;
변경한 코드에서는 클릭 이벤트가 한 번만 실행된다. 그리고 불필요한 추가 상태 변경이 발생하지 않아서 그런지theme 상태가 정상적으로 업데이트되었다.
클릭과 같이 이벤트가 비정상적일 땐 잊지 말고 preventDefault 메서드를 활용하자!
작성된 코드는 git에서 확인할 수 있다.
'공부합시다 > React' 카테고리의 다른 글
Authenticated Routes 사용기 (3) | 2025.07.25 |
---|---|
라이브러리 없이 Drag&Drop으로 리스트 순서 바꾸기 (0) | 2025.03.21 |
[기본 개념] React (1) | 2025.03.17 |
[React] webpack < 5 used to include polyfills for node.js core modules by default. (2) | 2022.11.28 |
[React] Router 추가하기 (0) | 2022.11.25 |