23.08.01 15:01 작성
·
1.4K
0
안녕하세요 제로초님!
회원가입을 하려면, 계속 아래와 같은 에러가 터미널에 뜹니다.
error: [TypeError: Cannot read property 'status' of undefined]
ERROR undefined
어디가 잘 못 된걸까요,,
.env파일 확인 해서 제 IP주소 확인했습니다.
signUp 부분을 확인해야하는건지,,
import React, {useCallback, useRef, useState, useEffect} from 'react';
import {
ActivityIndicator,
Alert,
Platform,
Pressable,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
import {NativeStackScreenProps} from '@react-navigation/native-stack';
import DismissKeyboardView from '../components/DismissKeyboardView';
import axios, {AxiosError} from 'axios';
import Config from 'react-native-config'; // 혹시 이거 설정법 아시나요
import {RootStackParamList} from '../../AppInner';
type SignUpScreenProps = NativeStackScreenProps<RootStackParamList, 'SignUp'>;
function SignUp({navigation}: SignUpScreenProps) {
const [loading, setLoading] = useState(false);
const [email, setEmail] = useState('');
const [name, setName] = useState('');
const [password, setPassword] = useState('');
const emailRef = useRef<TextInput | null>(null);
const nameRef = useRef<TextInput | null>(null);
const passwordRef = useRef<TextInput | null>(null);
useEffect(() => {
console.log('email: ', email);
console.log('name: ', name);
console.log('password: ', password);
}, [email, name, password]);
const onChangeEmail = useCallback((text: string) => {
setEmail(text.trim());
}, []);
const onChangeName = useCallback((text: string) => {
setName(text.trim());
}, []);
const onChangePassword = useCallback((text: string) => {
setPassword(text.trim());
}, []);
const onSubmit = useCallback(async () => {
if (loading) {
return;
}
if (!email || !email.trim()) {
return Alert.alert('알림', '이메일을 입력해주세요.');
}
if (!name || !name.trim()) {
return Alert.alert('알림', '이름을 입력해주세요.');
}
if (!password || !password.trim()) {
return Alert.alert('알림', '비밀번호를 입력해주세요.');
}
if (
!/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/.test(
email,
)
) {
return Alert.alert('알림', '올바른 이메일 주소가 아닙니다.');
}
if (!/^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$@^!%*#?&]).{8,50}$/.test(password)) {
return Alert.alert(
'알림',
'비밀번호는 영문,숫자,특수문자($@^!%*#?&)를 모두 포함하여 8자 이상 입력해야합니다.',
);
}
console.log(email, name, password);
try {
//:TODO log 삭제
console.log('LOGIN REQUEST');
console.log(Config.API_URL);
setLoading(true);
console.log(email);
console.log(name);
console.log(password);
const response = await axios.post(`${Config.API_URL}/user`, {
email,
name,
password,
});
console.log('response: ', response.data);
Alert.alert('알림', '회원가입 되었습니다.');
navigation.navigate('SignIn');
} catch (error) {
console.log('error: ', error);
const errorResponse = (error as AxiosError).response;
console.error(errorResponse);
if (errorResponse) {
Alert.alert('알림');
}
} finally {
setLoading(false);
}
}, [loading, navigation, email, name, password]);
const canGoNext = email && name && password;
return (
<DismissKeyboardView>
<View style={styles.inputWrapper}>
<Text style={styles.label}>이메일</Text>
<TextInput
style={styles.textInput}
onChangeText={onChangeEmail}
placeholder="이메일을 입력해주세요"
placeholderTextColor="#666"
textContentType="emailAddress"
value={email}
returnKeyType="next"
clearButtonMode="while-editing"
ref={emailRef}
onSubmitEditing={() => nameRef.current?.focus()}
blurOnSubmit={false}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.label}>이름</Text>
<TextInput
style={styles.textInput}
placeholder="이름을 입력해주세요."
placeholderTextColor="#666"
onChangeText={onChangeName}
value={name}
textContentType="name"
returnKeyType="next"
clearButtonMode="while-editing"
ref={nameRef}
onSubmitEditing={() => passwordRef.current?.focus()}
blurOnSubmit={false}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.label}>비밀번호</Text>
<TextInput
style={styles.textInput}
placeholder="비밀번호를 입력해주세요(영문,숫자,특수문자)"
placeholderTextColor="#666"
onChangeText={onChangePassword}
value={password}
keyboardType={Platform.OS === 'android' ? 'default' : 'ascii-capable'}
textContentType="password"
secureTextEntry
returnKeyType="send"
clearButtonMode="while-editing"
ref={passwordRef}
onSubmitEditing={onSubmit}
/>
</View>
<View style={styles.buttonZone}>
<Pressable
style={
canGoNext
? StyleSheet.compose(styles.loginButton, styles.loginButtonActive)
: styles.loginButton
}
disabled={!canGoNext || loading}
onPress={onSubmit}>
{loading ? (
<ActivityIndicator color="white" />
) : (
<Text style={styles.loginButtonText}>회원가입</Text>
)}
</Pressable>
</View>
</DismissKeyboardView>
);
}
const styles = StyleSheet.create({
textInput: {
padding: 5,
borderBottomWidth: StyleSheet.hairlineWidth,
},
inputWrapper: {
padding: 20,
},
label: {
fontWeight: 'bold',
fontSize: 16,
marginBottom: 20,
},
buttonZone: {
alignItems: 'center',
},
loginButton: {
backgroundColor: 'gray',
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 5,
marginBottom: 10,
},
loginButtonActive: {
backgroundColor: 'blue',
},
loginButtonText: {
color: 'white',
fontSize: 16,
},
});
export default SignUp;
아니면 AppInner부분인건지 모르겟습니다.
import SignIn from './src/pages/SignIn';
import SignUp from './src/pages/SignUp';
import Orders from './src/pages/Orders';
import Delivery from './src/pages/Delivery';
import Settings from './src/pages/Settings';
import * as React from 'react';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {useSelector} from 'react-redux';
import {RootState} from './src/store/reducer';
import useSocket from './src/hooks/useSocket';
import {useEffect} from 'react';
import EncryptedStorage from 'react-native-encrypted-storage';
import axios, {AxiosError} from 'axios';
import {Alert} from 'react-native';
import userSlice from './src/slices/user';
import {useAppDispatch} from './src/store';
import Config from 'react-native-config';
import orderSlice from './src/slices/order';
export type LoggedInParamList = {
Orders: undefined;
Settings: undefined;
Delivery: undefined;
Complete: {orderId: string};
};
export type RootStackParamList = {
SignIn: undefined;
SignUp: undefined;
};
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator<RootStackParamList>();
function AppInner() {
const dispatch = useAppDispatch();
const isLoggedIn = useSelector((state: RootState) => !!state.user.email);
console.log('isLoggedIn', isLoggedIn);
const [socket, disconnect] = useSocket();
// 앱 실행 시 토큰 있으면 로그인하는 코드
useEffect(() => {
const getTokenAndRefresh = async () => {
try {
const token = await EncryptedStorage.getItem('refreshToken');
if (!token) {
return;
}
const response = await axios.post(
`${Config.API_URL}/refreshToken`,
{},
{
headers: {
authorization: `Bearer ${token}`,
},
},
);
dispatch(
userSlice.actions.setUser({
name: response.data.data.name,
email: response.data.data.email,
accessToken: response.data.data.accessToken,
}),
);
} catch (error) {
console.error(error);
if ((error as AxiosError as any).response?.data.code === 'expired') {
Alert.alert('알림', '다시 로그인 해주세요.');
}
}
};
getTokenAndRefresh();
}, [dispatch]);
useEffect(() => {
const callback = (data: any) => {
console.log(data);
dispatch(orderSlice.actions.addOrder(data));
};
if (socket && isLoggedIn) {
socket.emit('acceptOrder', 'hello');
socket.on('order', callback);
}
return () => {
if (socket) {
socket.off('order', callback);
}
};
}, [dispatch, isLoggedIn, socket]);
useEffect(() => {
if (!isLoggedIn) {
console.log('!isLoggedIn', !isLoggedIn);
disconnect();
}
}, [isLoggedIn, disconnect]);
useEffect(() => {
axios.interceptors.response.use(
response => {
return response;
},
async error => {
const {
config,
response: {status},
} = error;
if (status === 419) {
if (error.response.data.code === 'expired') {
const originalRequest = config;
const refreshToken = await EncryptedStorage.getItem('refreshToken');
// token refresh 요청
const {data} = await axios.post(
`${Config.API_URL}/refreshToken`, // token refresh api
{},
{headers: {authorization: `Bearer ${refreshToken}`}},
);
// 새로운 토큰 저장
dispatch(userSlice.actions.setAccessToken(data.data.accessToken));
originalRequest.headers.authorization = `Bearer ${data.data.accessToken}`;
// 419로 요청 실패했던 요청 새로운 토큰으로 재요청
return axios(originalRequest);
}
}
return Promise.reject(error);
},
);
}, [dispatch]);
return isLoggedIn ? (
<Tab.Navigator>
<Tab.Screen
name="Orders"
component={Orders}
options={{title: '오더 목록'}}
/>
<Tab.Screen
name="Delivery"
component={Delivery}
options={{title: '내 오더'}}
/>
<Tab.Screen
name="Settings"
component={Settings}
options={{title: '내 정보'}}
/>
</Tab.Navigator>
) : (
<Stack.Navigator>
<Stack.Screen
name="SignIn"
component={SignIn}
options={{title: '로그인'}}
/>
<Stack.Screen
name="SignUp"
component={SignUp}
options={{title: '회원가입'}}
/>
</Stack.Navigator>
);
}
export default AppInner;
답변 4
0
0
2023. 08. 01. 16:29
[ios]에서 안 될 때는 Podfile에 pod 'react-native-config', :path => '../node_modules/react-native-config/react-native-config.podspec' 추가해보기
이것도 해보셨나요? 참고로 console.log(process.env.API_URL) signup쪽에 추가해서 주소 잘 나오나 확인해보시면 좋습니다.
0
2023. 08. 01. 15:06
보통 에러가 있으면 그 에러의 파일명과 줄 수 칸 수가 같이 나올텐데요. 백엔드 서버는 켜신 게 맞나요? 백엔드 서버에도 에러메시지 있을 겁니다.
2023. 08. 01. 17:20
console.log 찍었을 때 어디까지는 나오는데 어디부터 나오지 않는다는 걸 알려주셔야 합니다.