1. ToggleButton 컴포넌트 설명
initialState 초기 상태 값을 받아 애니메이션을 통해 토글 버튼의 상태를 UI에 반영onToggle이라는 함수를 받아 상태가 바뀔 때마다 부모 컴포넌트에 전달loading 상태에서는 버튼이 비활성화되어 사용자의 추가 입력을 막는 역할2. 애니메이션 처리
Animated 모듈을 사용하여 토글의 배경색과 아이콘의 이동을 부드럽게 전환 useRef로 애니메이션 값을 관리Animated.timing을 통해 상태 변화에 따른 애니메이션을 적용import React, {useState, useRef, useEffect} from 'react';
import {StyleSheet, TouchableOpacity, Animated} from 'react-native';
import {ToggleProps} from 'types/Common'; // 타입 정의 import
// ToggleButton 컴포넌트 정의
const ToggleButton: React.FC<ToggleProps> = ({
initialState, // 초기 상태 값
onToggle, // 상태 변경 시 호출되는 함수
loading = false, // 로딩 중일 때 버튼을 비활성화하기 위한 flag
}) => {
// 상태 관리를 위한 useState, 초기값으로 initialState를 사용
const [isOn, setIsOn] = useState(initialState);
// 애니메이션 값을 저장하는 useRef
const animatedValue = useRef(new Animated.Value(isOn ? 1 : 0)).current;
// 상태 변경 시 애니메이션 적용
useEffect(() => {
Animated.timing(animatedValue, {
toValue: isOn ? 1 : 0, // 상태에 따라 애니메이션 목표값 설정
duration: 400, // 애니메이션 지속 시간 (400ms)
useNativeDriver: true, // 성능 향상을 위한 Native Driver 사용
}).start(); // 애니메이션 시작
}, [isOn, animatedValue]);
// 버튼이 눌렸을 때 실행되는 함수
const handleToggle = () => {
if (!loading) { // 로딩 중이 아닐 때만 작동
const newState = !isOn; // 현재 상태를 반전
setIsOn(newState); // 상태 업데이트
onToggle(newState); // 부모 컴포넌트에 상태 변경 알림
}
};
// 아이콘이 이동할 위치 애니메이션 설정 (X축 이동)
const iconTranslateX = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [-2, 13], // 상태에 따라 X축 위치 변경
});
// 배경색 애니메이션 설정 (회색 -> 빨간색)
const bgColor = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: ['#AAA', '#ED423F'], // 상태에 따라 배경색 변경
});
return (
// Animated.View로 배경색 애니메이션 적용
<Animated.View style={[styles.toggleWrapper, {backgroundColor: bgColor}]}>
<TouchableOpacity
activeOpacity={0.8} // 버튼을 눌렀을 때 투명도 효과
onPress={handleToggle} // 버튼 클릭 시 실행되는 함수
disabled={loading} // 로딩 중일 때는 비활성화
>
{/* 아이콘 애니메이션 */}
<Animated.View
style={[styles.icon, {transform: [{translateX: iconTranslateX}]}]}
/>
</TouchableOpacity>
</Animated.View>
);
};
// 스타일 정의
const styles = StyleSheet.create({
toggleWrapper: {
borderRadius: 20, // 버튼의 테두리 둥글게
padding: 5, // 내부 여백
width: 40, // 버튼의 너비
height: 24, // 버튼의 높이
justifyContent: 'center', // 아이콘을 수직 가운데로 정렬
},
icon: {
width: 19, // 아이콘의 너비
height: 19, // 아이콘의 높이
backgroundColor: '#FFF', // 아이콘의 배경색
borderRadius: 30, // 아이콘을 둥글게 만듦
},
});
export default ToggleButton;
3. 핸들링 로직
handleToggle 함수에서는 로딩 상태가 아닐 때만 상태를 반전onToggle 함수는 부모 컴포넌트로 상태 변경을 전달하는 역할4. 스타일링
import ToggleButton from 'components/common/ToggleButton';
import React, {useState} from 'react';
import {View} from 'react-native';
const ToggleButtonTest = () => {
const [isOn, setIsOn] = useState(true);
const handleToggle = () => {
setIsOn(!isOn); // 상태 반전
};
return (
<View>
{/* ToggleButton 사용, 상태와 상태 변경 함수 전달 */}
<ToggleButton initialState={isOn} onToggle={handleToggle} />
</View>
);
};
export default ToggleButtonTest;
| option | description | type | required | default |
|---|---|---|---|---|
initialState | 초기 상태 값 | boolean | true | |
onToggle | 토글 시 동작하는 메소드 | function | true | |
loading | api 호출 시 로딩 상태 | boolean | false | true |
애니메이션과 함께 동작하는 토글 버튼을 사용한 화면입니다:

위 컴포넌트를 사용하면 React Native에서 커스텀 토글 버튼을 쉽게 구현할 수 있습니다. 애니메이션 효과와 로딩 상태 처리 기능을 통해 UX를 향상시킬 수 있으며, 다양한 프로젝트에 재사용 가능합니다.
좋은 라이브러리도 많이 있지만 아직 모르는 게 너무 많고 일단 뭐든 해보는 게 중요하다고 생각했기 때문에 직접 만들었고 어렵지 않게 구현할 수 있었다. 또 만들어보면서 많이 배울 수 있었기 때문에 좋은 경험이었던 것 같다.