react-native-contacts Possible Unhandled Promise Rejection (id: 0): TypeError: undefined is not an object

Maliethy·2021년 2월 1일
0

1. issue

'react-native-contacts'를 사용해 연락처 정보를 가져올 때 다음의 오류가 나왔다.

 Possible Unhandled Promise Rejection (id: 0): TypeError: undefined is not an object (evaluating '_reactNative.PermissionAndroid.requestMultiple')

2. solution

설정상의 오류인 줄 알고 헤맸는데 알고 봤더니 PermissionsAndroid를 PermissionAndroid로 s를 빼먹고 잘못 써서 나온 오류였다.

 const requestContactPermission = async () => {
    if (Platform.OS === 'ios') {
      console.warn('iOS');
      return true;
    } else {
      console.warn('Android');

      const granted = await PermissionsAndroid.requestMultiple([
        PermissionsAndroid.PERMISSIONS.WRITE_CONTACTS,
        PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
      ]);
      if (
        granted['android.permission.READ_CONTACTS'] ===
          PermissionsAndroid.RESULTS.GRANTED &&
        granted['android.permission.WRITE_CONTACTS'] ===
          PermissionsAndroid.RESULTS.GRANTED
      ) {
        return true;
      } else {
        return false;
      }
    }
  }; 

Android permissions을 설정하려면 API의 버전을 확인해야한다.
android > bundle.gradle에 있는 minSdkVersion의 값인 21이 API버전을 가리킨다.

buildscript {
    ext {
        buildToolsVersion = "29.0.2"
        minSdkVersion = 21
        compileSdkVersion = 29
        targetSdkVersion = 29
     }
    }

react-native-contacts를 보면 API 22버전 이하는 아래와 같이 설정해주면 된다고 나와있다.

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_PROFILE" />

그러나 나는 다음과 같이 설정해도 문제가 없었다.

<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

3. issue2

처음 렌더링할 때는 getContacts를 통해 android폰에 있는 연락처를 가져오지 않아 const [myContacts, setMyContacts] = useState('');와 같이 useState를 이용해 초기값을 세팅했다.
myContacts의 초기값이 string이라 map메소드를 썼을 때 아래와 같은 오류가 발생했다.

[Mon Feb 01 2021 22:18:52.833]  ERROR    TypeError: undefined is not a function (near '...myContacts.map...')

This error is located at:
    in App (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

4. solution2

const [myContacts, setMyContacts] = useState([]);로 값이 없을 시 빈 배열값을 넣어주니 해결되었다.

 const [myContacts, setMyContacts] = useState([]);
 const getContacts = () => {
    requestContactPermission().then((didGetPermission) => {
      if (didGetPermission) {
        Contacts.getAll()
          .then((contacts) => {
            // console.warn(contacts);
            setMyContacts(contacts);
          })
          .catch((err) => {
            console.error(err);
            throw err;
          });
      } else {
        alert('no permission');
      }
    });
  };
 return (
    <SafeAreaView>
      <ScrollView>
        <View style={styles.container}>
            {myContacts.map((item, idx) => {
            return (
              <Text key={idx}>
                {item.givenName}
                {item.familyName}
              </Text>
            );
          })}
          <Button title="load contacts" onPress={() => getContacts()} />         
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};
profile
바꿀 수 있는 것에 주목하자

0개의 댓글