https://www.figma.com/embed?embed_host=notion&url=https%3A%2F%2Fwww.figma.com%2Ffile%2FckYUAr2srqnzskNMzl98ED%2F서비스-Flow%3Ftype%3Dwhiteboard%26node-id%3D165-680%26t%3DZ4vS38qEW6RWKLTK-0
제공된 디자인에 맞춰 수정 진행
import { View, StyleSheet } from 'react-native';
import Text from '@/components/Text';
import Vote from '@/components/Vote';
import Button from '@/components/Button';
import { theme } from '@/theme/color';
import VoteIcon from '@/assets/icons/vote.svg';
import GhostLegIcon from '@/assets/icons/ghost-leg.svg';
import RouletteIcon from '@/assets/icons/roulette.svg';
function Roulette() {
return (
<View>
<Text>룰렛</Text>
</View>
);
}
function GhostLeg() {
return (
<View>
<Text>사다리타기</Text>
</View>
);
}
const BottomTab = ({ navigation }) => {
return (
<View
style={{
flex: 1,
flexDirection: 'row',
borderTopColor: '#DBDBDB',
borderTopWidth: 1,
maxHeight: 56,
}}
>
<Button
style={styles.tab}
color={{ color: '#3F3F3F' }}
text={
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<VoteIcon width={24} height={24} />
<Text>투표 만들기</Text>
</View>
}
onPress={() => navigation.push('투표 만들기')}
/>
<Button
style={styles.tab}
color={{ color: '#3F3F3F' }}
text={
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<GhostLegIcon width={24} height={24} />
<Text>사다리 타기</Text>
</View>
}
/>
<Button
style={styles.tab}
color={{ color: '#3F3F3F' }}
text={
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<RouletteIcon width={24} height={24} />
<Text>룰렛 만들기</Text>
</View>
}
/>
</View>
);
};
const styles = StyleSheet.create({
tab: {
flex: 1,
backgroundColor: theme.background,
justifyContent: 'center',
},
});
export default BottomTab;
// App.js
<Stack.Screen
name="투표 만들기"
component={Vote}
options={{
headerTitleAlign: 'center', // header title center
headerBackImageSource: // custom header BackImage
Platform.OS === 'android'
? require('@/assets/icons/cancle.png')
: { uri: 'back', width: 24, height: 24 },
headerTitleStyle: {
fontWeight: 'bold',
color: 'black',
},
headerRight: () => (
<Button
style={{ backgroundColor: theme.background }}
color={{ color: theme.main, fontSize: 20 }}
text="완료"
/>
),
}}
/>
완료 버튼 눌렀을 때 투표가 개설되어야 한다.
하지만 현재는 App.js에서 버튼을 생성해서 핸들링하기 어렵다.
버튼을 핸들링하기 위해서는 해당 컴포넌트안에서 생성해줘야한다.
// components/Vote
export default function Vote({ navigation }) {
...
useEffect(() => {
// header Right 완료 버튼
navigation.setOptions({
headerRight: () => (
<Button
style={{ backgroundColor: theme.background }}
color={{ color: theme.main, fontSize: 20 }}
text="완료"
onPress={handleSubmitVote}
/>
),
});
}, [navigation, items]);
const handleSubmitVote = () => {
console.log(title);
console.log(items);
console.log(getFormatDate(endDate));
console.log(muilple);
};
...
}
Vote 컴포넌트는 App.js에서 Navigation Stack에 등록되어 있어서, navigation prop을 전달받을 수 있다. 전달 받은 navigation에는 다양한 함수가 존재하지만 헤더를 건들기 위해서는 setOptions
를 사용할 것이다.
setOptions는 위 stack.screen처럼 navigation에 옵션을 추가할 수 있다. 그래서 이전에 작성해둔 headerRight를 그대로 가져와서 onPress 시 해당하는 함수를 등록해주면 된다.
여기서 주의할 점은 useEffect안에 작성했기 때문에 완료 시 변경된 값들을 의존성 배열에 등록해줘야만 변경된 값을 반영해서 내보낼 수 있다.
React-Native에서 기본적으로 제공하는 Switch 컴포넌트가 있다.
// components/Switch
import { Switch as RNSwitch } from 'react-native';
import { theme, voteTheme } from '@/theme/color';
import { useEffect, useState } from 'react';
const Switch = (props) => {
const { onParentState } = props;
const [isEnabled, setIsEnabled] = useState(false);
const toggleSwitch = () => {
setIsEnabled((previousState) => !previousState);
};
useEffect(() => {
if (onParentState) onParentState(isEnabled);
}, [isEnabled]);
return (
<RNSwitch
trackColor={{
false: voteTheme.optionSwitchFalseBackground,
true: theme.main,
}}
thumbColor={voteTheme.optionSwitchTrueText}
onValueChange={toggleSwitch}
value={isEnabled}
/>
);
};
export default Switch;