728x90
- 새 목표 추가 버튼 클릭
- 모달로 입력 창이 나타나고 목표추가
- 추가 완료시 모달창이 사라지고 다시 메인 창이 보여짐
- 화면 크기 이상 늘어날 시 스크롤 기능 작동
App.js
import { useState } from 'react';
import { StyleSheet, View, FlatList, Button} from 'react-native';
import { StatusBar } from 'expo-status-bar';
import GoalItem from './components/GoalItem';
import GoalInput from './components/GoalInput';
export default function App() {
const [modalIsVisible, setModalIsVisible] = useState(false)
const [courseGoals, setCourseGoals] = useState([]);
function startAddGoalHandler(){
setModalIsVisible(true);
}
function endAddGoalHandler(){
setModalIsVisible(false);
}
function addGoalHandler(enteredGoalText) {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
{ text: enteredGoalText, id: Math.random().toString() },
]);
endAddGoalHandler();
}
function deleteGoalHandler(id) {
setCourseGoals((currentCourseGoals) => {
return currentCourseGoals.filter((goal) => goal.id !== id);
});
}
return (
<>
<StatusBar style='light'/>
<View style={styles.appContainer}>
<Button title='새 목표 추가' color="#a065ec" onPress={startAddGoalHandler}/>
<GoalInput visible={modalIsVisible} onAddGoal={addGoalHandler} onCancel={endAddGoalHandler} />
<View style={styles.goalsContainer}>
<FlatList
data={courseGoals}
renderItem={(itemData) => {
return (
<GoalItem
text={itemData.item.text}
id={itemData.item.id}
onDeleteItem={deleteGoalHandler}
/>
);
}}
keyExtractor={(item, index) => {
return item.id;
}}
alwaysBounceVertical={false}
/>
</View>
</View>
</>
);
}
const styles = StyleSheet.create({
appContainer: {
flex: 1,
paddingTop: 50,
paddingHorizontal: 16,
backgroundColor: '#1e085a'
},
goalsContainer: {
flex: 5,
},
});
GoalInput 컴포넌트를 모달로 표현
visible 속성 modalsVisible 값을 넘긴다.
<GoalInput visible={modalIsVisible} onAddGoal={addGoalHandler} onCancel={endAddGoalHandler} />
useState로 변수 제어
const [modalIsVisible, setModalIsVisible] = useState(false)
추가(onAddGoal), 취소(onCancel) 를 할 때 실행.
function addGoalHandler(enteredGoalText) {
setCourseGoals((currentCourseGoals) => [
...currentCourseGoals,
{ text: enteredGoalText, id: Math.random().toString() },
]);
endAddGoalHandler();
}
function endAddGoalHandler(){
setModalIsVisible(false);
}
리액트에서 데이터 추가 코드 작성시 권장하는 방법
...currentCourseGoals 이전 값 복사
새 목표 추가 버튼 클릭시 모달창 visible
<Button title='새 목표 추가' color="#a065ec" onPress={startAddGoalHandler}/>
function startAddGoalHandler(){
setModalIsVisible(true);
}
FlatList에서 renderItem 으로 아이템 생성
renderItem={(itemData) => {
return (
<GoalItem
text={itemData.item.text}
id={itemData.item.id}
onDeleteItem={deleteGoalHandler}
/>
);
}}
const [courseGoals, setCourseGoals] = useState([]);
function deleteGoalHandler(id) {
setCourseGoals((currentCourseGoals) => {
return currentCourseGoals.filter((goal) => goal.id !== id);
});
}
람다표현과 filter으로 화면상 데이터 삭제
GoalInput.js
import { useState } from 'react';
import { View, TextInput, Button, StyleSheet, Modal , Image } from 'react-native';
function GoalInput(props) {
const [enteredGoalText, setEnteredGoalText] = useState('');
function goalInputHandler(enteredText) {
setEnteredGoalText(enteredText);
}
function addGoalHandler() {
props.onAddGoal(enteredGoalText);
setEnteredGoalText('');
}
return (
<Modal visible={props.visible} animationType=''> // 모달로 전체를 감싸준다.
<View style={styles.inputContainer}>
<Image style={styles.image} source={require('../assets/images/icons8.png')} />
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
value={enteredGoalText}
/>
<View style={styles.buttonContainer}>
<View style={styles.button}>
<Button title="Add Goal" onPress={addGoalHandler} color="#b180f0" />
</View>
<View style={styles.button}>
<Button title='취소' onPress={props.onCancel} color="#f31282"/>
</View>
</View>
</View>
</Modal>
);
}
export default GoalInput;
const styles = StyleSheet.create({
inputContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 16,
backgroundColor: '#311b6b'
},
textInput: {
borderWidth: 1,
borderColor: '#e4d0ff',
backgroundColor: '#e4d0ff',
color: '#120438',
borderRadius: 6,
width: '80%',
marginRight: 8,
padding: 12,
},
buttonContainer: {
marginTop: 10,
flexDirection: 'row'
},
button: {
width: '30%',
marginHorizontal: 8,
},
image: {
width: 100,
height: 100,
margin: 20
}
});
우선 props를 통해 전달된 속성들을 받아올 수 있다.
모달의 visible값을 props로 받아온 값으로 넣어준다.
<Modal visible={props.visible} animationType=''>
이미지 컴포넌트
<Image style={styles.image} source={require('../assets/images/icons8.png')} />
require 함수 파라미터로 상대경로를 넣어준다.
텍스트 input 컴포넌트
<TextInput
style={styles.textInput}
placeholder="Your course goal!"
onChangeText={goalInputHandler}
value={enteredGoalText}
/>
값이 변할 때 마다 해당 메소드핸들러를 실행 (goalInputHandler)
const [enteredGoalText, setEnteredGoalText] = useState('');
function goalInputHandler(enteredText) {
setEnteredGoalText(enteredText);
}
버튼 컴포넌트
<View style={styles.buttonContainer}>
<View style={styles.button}>
<Button title="Add Goal" onPress={addGoalHandler} color="#b180f0" />
</View>
<View style={styles.button}>
<Button title='취소' onPress={props.onCancel} color="#f31282"/>
</View>
</View>
전체 스타일을 잡기 위해 View로 한번 더 묶음
추가 버튼 클릭시 해당 메소드 실행
function addGoalHandler() {
props.onAddGoal(enteredGoalText);
setEnteredGoalText('');
}
실질적으로는 App에서 정의된 메소드로 기능 수행
GoalItem.js
import { StyleSheet, View, Text, Pressable } from 'react-native';
function GoalItem(props) {
return (
<View style={styles.goalItem}>
<Pressable
android_ripple={{ color: '#210644' }}
onPress={props.onDeleteItem.bind(this, props.id)}
style={({ pressed }) => pressed && styles.pressedItem}
>
<Text style={styles.goalText}>{props.text}</Text>
</Pressable>
</View>
);
}
export default GoalItem;
const styles = StyleSheet.create({
goalItem: {
margin: 8,
borderRadius: 6,
backgroundColor: '#5e0acc',
},
pressedItem: {
opacity: 0.5,
},
goalText: {
color: 'white',
padding: 8,
},
});
반복으로 생성된 GoalItem 컴포넌트
return (
<View style={styles.goalItem}>
<Pressable
android_ripple={{ color: '#210644' }}
onPress={props.onDeleteItem.bind(this, props.id)}
style={({ pressed }) => pressed && styles.pressedItem}
>
<Text style={styles.goalText}>{props.text}</Text>
</Pressable>
</View>
);
Pressable 컴포넌트로 누를 수 있는 뷰로 만들었다.
android 효과를 준다.
컴포넌트 눌렸을 때 실행되는 메소드
onPress={props.onDeleteItem.bind(this, props.id)}
this 값을 현재 컨텍스트로 설정
해당 요소가 눌렸을 때 스타일 설정
style={({ pressed }) => pressed && styles.pressedItem}
'Front-end > React\RN' 카테고리의 다른 글
리액트네이티브, 입력 검증 (0) | 2023.08.08 |
---|---|
리액트네이티브, 숫자 맞추기 앱 (커스텀 버튼, 누르기, 배경화면) (0) | 2023.08.07 |
리엑트네이티브 프로퍼티, 컴포넌트 나누기 (0) | 2023.05.22 |
리액트네이티브 스타일링, FlatList (0) | 2023.05.21 |
리액트 포털 createPortal, HTML 이동 (0) | 2023.01.11 |
댓글