Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- 리액트 네이티브 프로젝트 생성
- HTTP
- 리액트 네이티브
- React Native
- 정리
- 머신러닝
- 모두를위한딥러닝
- 깃 터미널 연동
- 모두를 위한 딥러닝
- 백준 4358번
- 문자열
- 백준
- 백준 4358 자바
- 스터디
- 데이터베이스
- 깃허브 토큰 인증
- 데베
- 네트워크
- 깃 연동
- 리액트 네이티브 시작하기
- SQL
- 백준 4949번
- 백준 5525번
- 딥러닝
- 모두의네트워크
- 자바
- 팀플회고
- 모두의 네트워크
- 지네릭스
- 깃허브 로그인
Archives
- Today
- Total
솜이의 데브로그
[React Native] 채팅 애플리케이션(2) 본문
로그인 화면
헤더 수정하기
options={{ headerBackTitleVisible: false }}
Screen 컴포넌트에서 위의 옵션을 추가하면 화면의 헤더에서 뒤로가기 버튼의 타이틀을 감출 수 있다.
노치 디자인 대응
- 내비게이션의 헤더를 감추면 노치 디자인에 대한 문제가 발생할 수 있으므로 대응해야한다.
- SafeAreaView 컴포넌트 이용
- 스타일에 설정해야 하는 padding 값을 얻는 받법
- useSafeAreaInsets 함수의 장점은 iOS 뿐만 아니라 안드로이드에서도 적용 가능한 padding 값을 전달한다는 점이다.
회원가입 화면
- 로그인 화면 제작 과정에서 만든 컴포넌트를 재사용하면 쉽고 빠르게 만들 수 있다.
src/screens/Signup.js
import React, { useState, useRef, useEffect } from "react";
import styled from "styled-components/native";
import { Image, Input, Button } from "../components";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { validateEmail, removeWhitespace } from "../utils/common";
// import { Text } from 'react-native';
const Container = styled.View`
flex: 1;
justify-content: center;
align-items: center;
background-color: ${({ theme }) => theme.background};
padding: 0 20px;
`;
const ErrorText = styled.Text`
align-items: flex-start;
width: 100%;
height: 20px;
margin-bottom: 10px;
line-height: 20px;
color: ${({ theme }) => theme.ErrorText };
`;
const Signup = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [passwordConfirm, setPasswordConfirm] = useState('');
const [errorMessage, setErrorMessage] = useState('');
const [disabled, setDisabled] = useState('');
const emailRef = useRef();
const passwordRef = useRef();
const passwordConfirmRef = useRef();
useEffect(() => {
let _errorMesage = '';
if (!name) {
_errorMesage = 'Please enter your name.';
} else if (!validateEmail(email)) {
_errorMesage = 'Please verify your email.';
} else if (password.length < 6) {
_errorMesage = 'The password must contain 6 characters at least.';
} else if (password !== passwordConfirm) {
_errorMesage = 'Passwords need to match.';
} else {
_errorMesage = '';
}
setErrorMessage(_errorMesage);
}, [name, email, password, passwordConfirm]);
useEffect(() => {
setDisabled(
!(name && email && password && passwordConfirm && !errorMessage)
);
}, [name, email, password, passwordConfirm, errorMessage]);
const _handleSignupButtonPress = () => {};
return(
<KeyboardAwareScrollView
contentContainerStyle={{ flex:1 }}
extraScrollHeight={20}
>
<Container>
<Image rounded />
<Input
label="Name"
value={name}
onChangeText={text => setName(text)}
onSubmitEditing={() => {
setName(name.trim());
emailRef.current.focus();
}}
onBlur={() => setName(name.trim())}
placeholder="Name"
returnKeyType="next"
/>
<Input
ref={emailRef}
label="Email"
value={email}
onChangeText={text => setEmail(removeWhitespace(text))}
onSubmitEditing={() => passwordRef.current.focus()}
placeholder="Email"
returnKeyType="next"
/>
<Input
ref={passwordRef}
label="Password"
value={password}
onChangeText={text => setPassword(removeWhitespace(text))}
onSubmitEditing={() => passwordConfirmRef.current.focus()}
placeholder="Password"
returnKeyType="done"
isPassword
/>
<Input
ref={passwordConfirmRef}
label="Password Confirm"
value={passwordConfirm}
onChangeText={text => setPasswordConfirm(removeWhitespace(text))}
onSubmitEditing={_handleSignupButtonPress}
placeholder="Password"
returnKeyType="done"
isPassword
/>
<ErrorText>{errorMessage}</ErrorText>
<Button
title="Signup"
onPress={_handleSignupButtonPress}
disabled={disabled}
/>
</Container>
</KeyboardAwareScrollView>
);
};
export default Signup;
- 입력받아야하는 값이 많아졌으므로 유효성 검사와 오류 메시지의 종류가 많아졌다.
- useEffect를 이용해 관련된 값이 변할 때마다 적절한 오류 메시지가 렌더링되도록 한다.
화면 스크롤
- flex: 1 스타일을 설정하면 컴포넌트가 차지하는 영역이 부모 컴포넌트 영역만큼으로 한정되므로, 컴포넌트의 크기에 따라 화면을 넘어가서 스크롤이 생성되도록 flex:1 을 삭제한다.
- contentContainerStyle을 삭제하고 화면의 위아래에 약간의 여유 공간을 두기 위해 Container 컴포넌트의 padding 값을 수정한다.
src/components/Image.js
const ButtonContainer = styled.TouchableOpacity`
background-color: ${({ theme }) => theme.imageButtonBackground};
position: absolute;
bottom: 0;
right: 0;
width: 30px;
height: 30px;
border-radius: 15px;
justify-content: center;
align-items: center;
`;
const ButtonIcon = styled(MaterialIcons).attrs({
name: 'photo-camera',
size: 22,
})`
color: ${({ theme }) => theme.imageButtonIcon};
`;
const PhotoButton = ({ onPress }) => {
return(
<ButtonContainer onPress={onPress}>
<ButtonIcon />
</ButtonContainer>
);
};
- Image 컴포넌트에서 사진 변경하기 버튼으로 사용할 PhotoButton 컴포넌트 생성
- 추가된 버튼은 Iamge 컴포넌트의 props로 전달되는 showButton의 값에 따라 렌더링 여부가 결정되도록 작성
- 버튼을 클릭하면 기기의 사진첨에 접근해서 선택된 사진의 정보를 가져오는 기능 추가
expo install expo-image-picker
src/components/Image.js
const Image = ({ url, imageStyle, rounded, showButton, onChangeImage }) => {
useEffect(() => {
(async () => {
try{
if (Platform.OS === 'ios'){
const { status } = await Permissions.askAsync(
Permissions.CAMERA_ROLL
);
if (status !== 'granted'){
Alert.alert(
'Photo Permission',
'Please turn on the camera roll permissions.'
);
}
}
} catch (e) {
Alert.alert('Photo Permission Error', e.message);
}
})();
}, []);
const _handleEditButton = async () => {
try{
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});
if (!result.cancelled){
onChangeImage(result.uri);
}
} catch(e) {
Alert.alert('Photo Error', e.message);
}
};
- 사진첩에 접근하기 위해 사용자에게 권한을 요청하는 과정이 필요하므로 권한을 요청하는 부분을 추가한다.
- 사진 변경 버튼을 클릭하면 호출되는 함수에서 기기의 사진에 접근하기 위해 호출되는 라이브러리 함수는 다음 값들을 포함한 객체를 파라미터로 전달받는다.
- mediaTypes : 조회하는 자료의 타입
- allowsEditing : 이미지 선택 후 편집 단계 진행 여부
- aspect : 안드로이드 전용 옵션으로 이미지 편집 시 사각형의 비율 ([x,y])
- quality : 0~1 사이의 값을 받으며 압축 품질을 의미 (1: 최대 품질)
src/screens/Signup.js
return(
<KeyboardAwareScrollView extraScrollHeight={20}>
<Container>
<Image
rounded url={photoUrl}
showButton
onChangeImage={url => setPhotoUrl(url)}
/>
기기에서 권한 요청을 수락하면 기기의 사진에 접근할 수 있고, 사진을 선택하면 Image 컴포넌트에서 선택한 사진이 렌더링 되는 것을 확인할 수 있다.
로그인과 회원가입
파이어베이스의 인증을 이용해 로그인과 회원가입 기능을 만들어보자.
로그인
- 생성된 사용자가 없으므로 파이어베이스 콘솔에서 사용자를 추가하고 로그인 기능을 만든다.
'dev > React native' 카테고리의 다른 글
[React Native] 채팅 애플리케이션 만들기 (0) | 2021.12.26 |
---|---|
[React Native] Navigation (0) | 2021.11.21 |
[React Native] Context API (0) | 2021.11.14 |
[React Native] Hooks (0) | 2021.11.12 |
[React Native] 할 일 관리 애플리케이션(2) (0) | 2021.11.06 |