저번 시간에 @react-navigation-native를 이용해서 페이지 이동까지 구현했습니당.
오늘 해야 할 것은 태그에 적힌 메세지를 읽고 해당하는 페이지로 이동해야합니다.

nfc-manager 사용법

 

GitHub - revtel/react-native-nfc-manager: React Native NFC module for Android & iOS

React Native NFC module for Android & iOS. Contribute to revtel/react-native-nfc-manager development by creating an account on GitHub.

github.com

설치하고 아래에 있는 예제 코드를 사용하면 tag가 읽혀지고 값을 얻을 수 있습니다.

components/NfcReader.js

import React from 'react';
import {TouchableOpacity, View, Text, StyleSheet} from 'react-native';
import NfcManager, {Ndef, NfcTech} from 'react-native-nfc-manager';

const NfcReader = ({setPageName}) => {
  const readNdef = async () => {
    try {
      await NfcManager.requestTechnology(NfcTech.Ndef);
      const tag = await NfcManager.getTag();
      setPageName(Ndef.text.decodePayload(tag.ndefMessage[0].payload));
    } catch (ex) {
      console.warn('Oops!', ex);
    } finally {
      NfcManager.cancelTechnologyRequest();
    }
  };

  return (
    <View>
      <TouchableOpacity onPress={readNdef} style={styles.button}>
        <Text style={styles.text}>태그 읽기</Text>
      </TouchableOpacity>
    </View>
  );
};
const styles = StyleSheet.create({
  button: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
  },
  text: {
    color: 'black',
  },
});
export default NfcReader;

tag에 찍히는 콘솔은 [10, 145, 20, 44] 같은 숫자로 오는데 Ndef.text.decodePayload()을 사용하면 글자로 바꿀수있음

components/NfcNavigator.js

import {useEffect, useState} from 'react';
import React from 'react';
import {useNavigation} from '@react-navigation/native';
import NfcReader from './NfcReader';

const NfcNavigator = () => {
  const navigation = useNavigation();
  const [pageName, setPageName] = useState('');

  useEffect(() => {
    if (pageName !== '') {
      navigation.navigate(pageName);
    }
  }, [pageName]);

  return <NfcReader setPageName={setPageName} />;
};

export default NfcNavigator;

useNavigation()을 사용하면 navigate() 을 사용할 수 있음.
NfcReader.js에서 태그를 읽고 pageName을 변경하고 해당하는 화면으로 전환시킴

두개를 컴포넌트화 시켜서 어디서든 사용할수있게끔 했는데 지금은 버튼형식이고 토글형식으로 할지 아니면 언제든 태깅할수있게 할지는 미지수.. 일단 버튼으로

 

react-navigation 사용법
 

Navigating Between Screens · React Native

Mobile apps are rarely made up of a single screen. Managing the presentation of, and transition between, multiple screens is typically handled by what is known as a navigator.

reactnative.dev


App.js

import {NavigationContainer} from '@react-navigation/native';
import React from 'react';
import {StyleSheet} from 'react-native';
import Home from './screens/Home.js';
import FirstPage from './screens/FirstPage';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={Home} />
        <Stack.Screen name="Page1" component={FirstPage} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;

 

screen/Home.js

import React from 'react';
import {View, Text, Button, TouchableOpacity, StyleSheet} from 'react-native';

const Home = ({navigation}) => {

  return (
    <View>
      <TouchableOpacity style={styles.button}>
        <Text style={{color: 'black'}}>버튼입니다</Text>
      </TouchableOpacity>
      <Text>Home입니당</Text>
      <Button title="Page1 열기" onPress={() => navigation.navigate('Page1')} />
    </View>
  );
};

const styles = StyleSheet.create({
  button: {
    alignItems: 'center',
    backgroundColor: '#DDDDDD',
    padding: 10,
  },
});

export default Home;

 

screen/FirstPage.js

import React from 'react';
import {View, Text} from 'react-native';

const FirstPage = () => {
  return (
    <View>
      <Text>FirstPage</Text>
    </View>
  );
};

export default FirstPage;

 

첫 화면

첫 화면으로 Home.js에 해당하는 화면이 나옴.
PAGE1 열기 버튼을 누르면 FirstPage.js가 나옴

 

 

<ScrollView 
	pagingEnabled 
    horizontal 
    showsHorizontalScrollIndicator={false} 
    contentContainerStyle={style.weather}>
</ScrollView>

ScrollView는 많은 props을 가지고 있어서 따로 봐야 할 정도임

pagingEnabled 는 한 페이지를 스크롤을 끈끈하게 만든다 해야하나 자유로운 스크롤이 아닌 해당하는 width만큼 화면이 변함.. 말로 설명이 안됨.. 

style적용시 반드시 contentContainerStyle을 사용

<View>의 경우 기본적으로 display: flex; 가 적용됐다고 생각하면된다.
|브라우저의 경우 flex-direction: row; 인 반면 RN에서는 flexDirection: column임

import { View } from "react-native";

export default function App() {
  return (
    <View style={{ flex: 1 }}>
      <View style={{ flex: 1, backgroundColor: "tomato" }}></View>
      <View style={{ flex: 3, backgroundColor: "teal" }}></View>
      <View style={{ flex: 1, backgroundColor: "orange" }}></View>
    </View>
  );
}

크기조정을 width: 100px; height: 200px;식으로 조정하지 않고 flex: 숫자 같이 정의해서 사용

React Native에서 많은 Component와 APIs를 지원했고 RN 개발팀이 직접 개발하기에 버그픽스가 빨랐다고 함.

그러나 너무 많은 기능을 만들고 하는데는 그 만큼 많은 리소스가 들어가기 때문에 RN에서는 필요한 것들만 추려낸 Component와 APIs를 제공하고 나머지는 third party library로 사용함. expo에서 제공하거나 사용자들이 만들어낸 것을 사용함
예) Statusbar, Navigator

React Native는 웹 브라우저로 동작 하는 것이 아닌 모바일 OS와 통신하며 모바일 어플리케이션을 동작시킴.

브라우저로 동작하는 것이 아니기때문에 div, span, p 등의 태그는 사용할 수 없음.
<View>, <Text> 등의 특정 태그를 사용해야 함.

style의 경우 css와 비슷하지만 사용할 수 없는 속성들도 있음. 따로 정의해서 써도 되고 요소마다 각각 적용도 가능.
StyleSheet.create()를 사용 시 자동완성 사용가능 (굳이 사용치 않아도 됨)

async function getData() {
  let rawResponse = await fetch("https://jsonplaceholder.typicode.com/posts");
  let jsonResponse = await rawResponse.json();
  console.log(rawResponse);
  console.log(jsonResponse);
}

getData();

jsonplaceholder라는 사이트를 이용해 통신으로 데이터를 받아옴. 이처럼 누구나 데이터를 가져다 쓸 수 있게 열어놓은 것들을 open API라고 함.

api 호출시도 전에 배운것과 같이 동기처리를 해야함

결과 값

function delay(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function helloAsync() {
  await delay(3000);
  return "hello async";
}

async function main() {
  const res = await helloAsync(); // 여기
  console.log(res);
}

main();

여기라 표시한 부분에 await를 쓰지 않고 실행하면 Promise{<pending>} 이라고 콘솔에 찍히게 된다 그 이유는 비동기의 코드가 끝나지않고 콘솔에 출력했기 때문.

동기적으로 3초 후에 출력하기 위해 await를 걸어야 함

'Javascript' 카테고리의 다른 글

[JavaScript] API 호출하기  (0) 2022.04.05
[JavaScript] Promise - 콜백 지옥에서 탈출하기  (0) 2022.04.05
[JavaScript] 동기 & 비동기  (0) 2022.04.05
[JavaScript] Spread 연산자  (0) 2022.04.05
[JavaScript] 비구조화 할당  (0) 2022.04.05
function taskA(a, b, callback) {
  setTimeout(() => {
    const result = a + b;
    callback(result);
  }, 2000);
}

function taskB(a, callback) {
  setTimeout(() => {
    const result = a * 2;
    callback(result);
  }, 3000);
}

taskA(3, 4, (a_res) => {
  console.log("taskA : " + a_res);
  taskB(a_res, (b_res) => {
    console.log("taskB : " + b_res);
  });
});

이러한 콜백지옥의 코드를 해결하기위해 Promise 객체를 사용함.
Promise객체는 resolve(성공)시와, reject(실패)시의 처리를 각각 할 수 있음.

function taskA(a, b) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const result = a + b;
      resolve(result);
    }, 2000);
  });
}

function taskB(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const result = a * 2;
      resolve(result);
    }, 3000);
  });
}

taskA(3, 4).then((a_res) => {
  console.log("taskA : " + a_res);
  taskB(a_res).then((b_res) => {
    console.log("taskB : " + b_res);
  });
});

프로미스가 반환되고 성공시의 처리를 위해 .then()을 사용

function taskA(a, b) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const result = a + b;
      resolve(result);
    }, 2000);
  });
}

function taskB(a) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const result = a * 2;
      resolve(result);
    }, 3000);
  });
}

taskA(3, 4)
  .then((a_res) => {
    console.log("taskA : " + a_res);
    return taskB(a_res);
  })
  .then((b_res) => {
    console.log("taskB : " + b_res);
  });

위의 코드를 더 간결히 표현할 수 있음

동기와 비동기를 이해하기 위해선 쓰레드를 알아야함.
자바스크립트라는 카페에는 직원이 하나라서 여러 한 테이블의 주문씩 밖에 처리를 못함..ㅠ
A테이블에 아아 2 개 B테이블에 아아 3 개 일 경우 2 개 만들고 서빙하고 3 개 만들고 서빙하는 형태인데 그럼 B테이블에 늦게 서빙되므로 컴플레인이 많이 접수됨..
그래서 직원에게 5개를 동시에 만들고 갯수가 채워지는데로 서빙하라고 시켜야함. 왜냐하면 자바스크립트 카페는 직원이 하나(싱글쓰레드)이기 때문임...

function sleep(sec) {
  return new Promise((resolve) => setTimeout(resolve, sec * 1000));
}

const makeCoffee = async (table, ea) => {
  await sleep(ea).then(() => {
    console.log(`${table} 테이블 서빙완료!`);
  });
};

async function serving() {
  let start = new Date();
  await makeCoffee("A", 2);
  await makeCoffee("B", 3);
  let end = new Date();
  console.log((end - start) / 1000);
}
serving();

// A 테이블 서빙완료!
// B 테이블 서빙완료!
// 5.002

위 코드는 A테이블과 B테이블에서 각각 2개, 3개의 커피를 주문하고 총 걸리는 시간을 출력하는 코드임
보다시피 총 걸리는 시간은 5초정도가 걸림. 당연한거아닌가? 싶지만 비동기 코드인 setTimeout코드로 작성한다면 두 개를 동시에 하기 때문에 3초정도가 걸림

동기와 비동기는 자바스크립트를 입문하면서 좌절하는 첫 번째 관문이 아닌가 싶기도...

 

+ Recent posts