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에서 확인할 수 있다.

+ Recent posts