# 터치

앱 내에서 헤더 두 버튼 중 하나를 클릭하면 색이 투명해지는 효과를 구현하고자 합니다. 이때 리액트 useState 훅을 사용하면 되는 것 까지 알고 있으므로 onClick 이벤트 정의와 함께 코드를 작성해봅니다.

export default function App() {
    const [clicked, setClicked] = useState(false);
    const one = () => {
        setClicked(true);
    };
    const two = () => {
        setClicked(false);
    };
    return (
        <View style={styles.container}>
            <StatusBar style='auto' />
            <View style={styles.header}>
                <Text
                    onClick={one}
                    style={{
                        ...styles.btnText,
                        color: clicked ? theme.grey : 'white',
                    }}
                >
                    Work
                </Text>
                <Text
                    onClick={two}
                    style={{
                        ...styles.btnText,
                        color: !clicked ? theme.grey : 'white',
                    }}
                >
                    Travel
                </Text>
            </View>
        </View>
    );
}

앱에서는 onClick메서드 등록만으로 동작에 대해 구현할 수 없습니다. 터치 감지를 위한 특별한 컴포넌트를 사용해야 합니다.

# Touchable

# 1. TouchableOpacity

TouchableOpacity 컴포넌트는 일반 박스 컴포넌트이며 터치 대상에 대해 이벤트 감지를 리스닝하는 컴포넌트입니다. 특별히 TouchableOpacity 컴포넌트는 클릭 시 투명도가 바뀌는 트랜지션 효과를 기본적으로 갖습니다.

touch

TouchableOpacity가 가장 일반적으로 사용됩니다. 다른 Touchable 컴포넌트와 마찬가지로 onPress 관련 프로퍼티를 갖습니다.

# 2. TouchableHighlight

TouchableHighlight도 역시 박스 컴포넌트이고 onPress 프로퍼티에 터치 이벤트 리스너를 받습니다. onPress 리스닝 외에 터치의 인앤아웃, 터치를 유지하는 동작들에 대해 리스닝 할 수 있습니다.

리액트 웹앱에서 온클릭 이벤트 리스너를 전달했던 것과 동일하게 사용합니다.

function App() {
    const onPress = () => {
        console.log('Pressed!');
    };
    return (
        <View>
            <TouchableHighlight onPress={onPress}>
                <Text>Hello!</Text>
            </TouchableHighlight>
        </View>
    );
}

위의 컴포넌트도 기본적인 트랜지션 효과는 가지고 있습니다.

# 3. TouchableWithoutFeedback

컴포넌트 이름대로 터치에 대한 피드백을 제공하지 않습니다. onPress 프로퍼티로 프레스에 대한 이벤트 리스너를 받고, UI 및 그래픽 변화 없이 내부적인 로직을 처리할때 사용합니다.

function App() {
    const onPress = () => {
        console.log('Pressed!');
    };
    return (
        <View>
            <TouchableWithoutFeedback onPress={onPress}>
                <Text>Hello!</Text>
            </TouchableWithoutFeedback>
        </View>
    );
}
export default function App() {
    const [working, setWorking] = useState(false);

    const one = () => {
        setWorking(true);
    };

    const two = () => {
        setWorking(false);
    };

    return (
        <View>
            <View>
                <TouchableOpacity onPress={one}>
                    <Text
                        style={{
                            ...styles.btnText,
                            color: working ? 'white' : theme.grey,
                        }}
                    >
                        One
                    </Text>
                </TouchableOpacity>
                <TouchableOpacity onPress={two}>
                    <Text
                        style={{
                            ...styles.btnText,
                            color: !working ? 'white' : theme.grey,
                        }}
                    >
                        Two
                    </Text>
                </TouchableOpacity>
            </View>
        </View>
    );
}

# TextInput

앱에서 텍스트 입력을 하려면 TextInput 컴포넌트를 사용해야합니다. 다음의 링크를 (opens new window) 참조하세요.

다양한 프로퍼티들이 있는데, 그 중 몇 가지를 보면 다음과 같습니다.

  1. keyboardType - 입력 양식에 따라 기기의 키보드 형태를 다르게 제공해줍니다. default number-pad decimal-pad numeric email-address phone-pad 등이 있고 OS마다 따로 제공되는 것들도 있습니다.
  2. onChangeText - 입력한 텍스트를 받아올 수 있습니다.
  3. returnKeyType- (string) 제출버튼의 형태를 변경할 수 있습니다.
  4. secureTextEntry - (boolean) 비밀번호 입력과 같은 형태로 입력 문자열이 가려집니다.
  5. multiline - (boolean) 줄바꿈을 통해 여러 라인에 걸쳐 입력할 수 있게 됩니다.

onChangeText는 프로퍼티 값으로 함수를 받습니다. 리액트 웹앱에서는 event.currentTarget.value와 같이 자식 요소로 찾아나가는 방식으로 값을 추적하지만 리액트 네이티브 앱에서는 event 자체가 값이 됩니다.

export default function App() {
    // event 파라미터를 출력
    const onChangeText = (e) => {
        console.log(e);
    };

    return (
        <View>
            <TextInput
                placeholder={
                    working ? 'Add a To do' : 'Where do you want to go?'
                }
                onChangeText={onChangeText}
            />
        </View>
    );
}

리액트와 마찬가지로 인풋값에 대한 제어를 위해 value 프로퍼티와 상태값을 바인딩 해줘야 합니다.

export default function App() {
    const [text, setText] = useState('');

    const onChangeText = (payload) => {
        setText(payload);
    };

    return (
        <View>
            <TextInput
                placeholder={
                    working ? 'Add a To do' : 'Where do you want to go?'
                }
                onChangeText={onChangeText}
                value={text}
            />
        </View>
    );
}

텍스트 인풋에 대한 제출 이벤트 감지를 위해서 onSubmitEditing 프로퍼티를 활용합니다. 리액트 앱에서 했던 것과 동일한 방식으로 하되, event.preventDefault()메서드를 호출할 필요는 없습니다.

내부에서 데이터 유효성 검사를 진행하고 state관리로 마무리 짓습니다. 이때 인풋값 트래킹을 위해서 TextInput 컴포넌트에 value 프로퍼티를 등록해놔야 합니다.

# AsyncStorage

리액트 웹앱 초기 단계에 항상 제작해보는 토이 프로젝트로 투두리스트가 있습니다. 웹앱에서는 브라우저 LocalStorage라는 곳에 데이터를 저장하여 브라우저 종료 후 재접속 해도 데이터가 로드되는 것들을 활용할 수 있었습니다.

모바일 앱에서는 이와 같은 역할을 AsyncStorage가 하게 됩니다. 아래 명령어를 입력하여 설치합니다. 공식문서 링크 (opens new window)를 참조하세요.

expo install @react-native-async-storage/async-storage

자바스크립트 파일에 AsyncStorage를 임포트 합니다.

import AsyncStorage from '@react-native-async-storage/async-storage';

스토리지에 값을 저장하는 방법은 아래와 같습니다. async - await 구문으로 저장해야하며 string형태만 저장 가능합니다. 객체를 저장하고 싶은 경우 JSON.stringify로 전달해야합니다.

const storeData = async (value) => {
    try {
        await AsyncStorage.setItem('@storage_Key', value);
    } catch (e) {
        // saving error
    }
};

스토리지에 대한 키값은 골뱅이@ 표시를 앞에 두고 문자열로 표기합니다.

const getData = async () => {
    try {
        const value = await AsyncStorage.getItem('@storage_Key');
        if (value !== null) {
            // value previously stored
        }
    } catch (e) {
        // error reading value
    }
};

스토리지에서 저장한 값을 불러오기 위해서는 위의 코드를 실행합니다. 저장 시 등록했던 스토리지 키값을 전달하면 됩니다. 이전에 JSON.stringify로 저장했다면 파싱을 해야할 것이고, 기본적으로 문자열로 리턴됩니다.

각종 에러처리를 위해 try~catch 구문을 사용하도록 습관을 들이는 것이 좋습니다.

# Alert API

Alert API 공식문서 (opens new window)

Alert API는 알럿 창을 띄웁니다. 단순 알람 외에도 알럿 창 확인 및 캔슬 버튼 클릭에 따라 상호작용도 이루어지게 됩니다.

Alert객체 정적 메서드로써 Alert.promptAlert.alert 메서드가 있습니다. prompt는 ios에서만 지원하는 메서드입니다.

Alert.alert 메서드는 세개의 파라미터를 받습니다.

  1. title - 큰 글씨로 표기됨
  2. message - 알럿창 타이틀 아래에 작게 디스크립션이 달림
  3. buttons - 알럿창에 대한 버튼 정의
Alert.alert('지울거냐???', '진짜??', [
    {
        text: '지워',
        onPress: () => {
            console.log('지웠다');
        },
    },
    { text: '싫어' },
]);

위와 같이 사용합니다. 첫번째와 두번째 파라미터는 메세지로 띄울 문자열을 전달하면 됩니다. 세 번째 파라미터의 경우 배열 내에 객체들을 전달하면 됩니다.

배열에 전달할 버튼 객체 프로퍼티들은 다음과 같습니다.

  1. text - 알럿창 버튼 텍스트
  2. onPress - 해당 버튼 클릭 시 상호작용할 함수
  3. style - ios에서만 지원하는 프로퍼티이며, destructive를 지정할 수 있습니다. 지정할 경우 알럿창 버튼 색이 붉은색으로 변경됩니다.