텍스트를 입력하면 (개발자도구에서 해당 element를 선택해놓고 텍스트입력을 해보면) <br>태그가 텍스트 입력했을 때 사라져있음을 볼 수 있다.
하지만 IE에서는 텍스트를 입력했어도 뒤에 <br /> 태그가 남아있었다.
두 번째 차이점, range의 범위가 다르다.
let selection = document.getSelection();
let range = selection.getRangeAt(0);
let currentNode = range.startContainer;
currentNode를 확인해보면 Chrome에서는 한글을 입력에 enter를 쳐서 확인해도 range의 startOffset과 endOffset이 같은데, IE에서는 한글을 입력중에 엔터를 친 경우에 아직 조합이 끝났다고 보지않아 startOffset과 endOffset이 차이가 있었다.
// AS-IS
function App() {
/* 여기에서 키보드 타자를 칠 때마다 (onChange될 때 마다)
setFirstName 을 통해 함수를 호출하고 다시 렌더링 되는데,
re-rendering performance를 최적화 하기 위해서는,
<PageContent /> 는 input의 state에 영향을 받지 않으므로
input의 state를 다루는 컴포넌트를 따로 만든다. */
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}
// TO-BE
function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}
function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}
/* 이 경우 performance가 상당히 향상되는데,
이제는 키입력에 따라 onChange 이벤트가 호출될 때,
SignupForm만 다시 렌더링하기 때문이다. */
import React from 'react';
import {Text} from 'react-native';
// 컴포넌트는 함수로 시작.
const Cat = () => {};
// 컴포넌트를 청사진으로 간주. 함수 컴포넌트가 return하는 무엇이든간에 React element로 랜더링 된다.
// React element는 스크린에 보고싶은 것을 묘사해줌.
// 예시로 <Text>를 렌더링하는 Cat 컴포넌트.
const Cat = () => {
return <Text>Hello, I am your cat!</Text>;
};
// export default를 통해 어플에 걸쳐서 사용할 수 있게 export 할 수 있다.
export default Cat;
Curly Braces
import React from 'react';
import {Text} from 'react-native';
// 중괄호{} 안에 변수 값을 넣을 수 있다.
const Cat = () => {
const name = 'Maru';
return <Text>Hello, I am {name}!</Text>;
};
const getFullName = (
firstName: string,
secondName: string,
thirdName: string,
) => {
return firstName + ' ' + secondName + ' ' + thirdName;
};
// 중괄호{} 안에 함수를 넣을 수 있다.
const Cat = () => {
return <Text>Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!</Text>;
};
export default Cat;
이런 JSX 문법은 React library안에 있는 것이므로 import React from 'react' 를 작성하지 않으면 기능하지 않는다.
import React from 'react';
import {Text, TextInput, View} from 'react-native';
const Cat = () => {
return (
// <View>안에 <Text>와 <TextInput>을 들여쓰면 React Native는 함께 랜더링 한다.
<View>
<Text>Hello, I am...</Text>
<TextInput
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
}}
defaultValue="Name me!"
/>
</View>
);
};
export default Cat;
import React from 'react';
import {Text, View} from 'react-native';
const Cat = () => {
return (
<View>
<Text>I am also a cat!</Text>
</View>
);
};
// 다른 컴포넌트를 렌더링하는 컴포넌트를 parent component라고 한다.
// 여기에서는 Cafe가 parent component이고, Cat이 child component이다.
const Cafe = () => {
return (
<View>
<Text>Welcome!</Text>
<Cat />
<Cat />
<Cat />
</View>
/* Cat 컴포넌트를 <Cat> 을 사용함으로써 여러번 렌더링 시킬 수 있다. */
);
};
export default Cafe;
import React from 'react';
import {Text, View} from 'react-native';
//Props는 properties의 줄임말로 Props를 통해 React component를 커스터마이징 할 수 있다.
// 각각의 Cat이 다른 name을 갖게 하는 예제이다.
type CatProps = {
name: string;
};
const Cat = (props: CatProps) => {
return (
<View>
<Text>Hello, I am {props.name}!</Text>
</View>
);
};
const Cafe = () => {
return (
<View>
<Cat name="Maru" />
<Cat name="Jellylorum" />
<Cat name="Spot" />
</View>
);
};
export default Cafe;
import React from 'react';
import {Text, View, Image} from 'react-native';
const CatApp = () => {
return (
/* <Image>를 사용할 경우 source라는 prop을 이용한다.
{{ }} 를 주목해보면 두 개의 중괄호가 있다.
JSX에서 JavaScript 값은 {}로 참조되는데, 이것은 문자열보다 props로 넘길 때 유용하다.
하지만 JS오브젝트 또한 중괄호로 표시된다.
따라서 JS오브젝트를 JSX에서 넘길 때 {}로 감싸게 된다.*/
<View>
<Image
source={{
uri: 'https://reactnative.dev/docs/assets/p_cat1.png',
}}
style={{width: 200, height: 200}}
/>
<Text>Hello, I am your cat!</Text>
</View>
);
};
export default CatApp;
State
컴포넌트가 어떻게 보여지는지 설정하는데 사용하는 argument --> props
컴포넌트의 개인 데이터 저장소 --> state
state는 사용자와의 상호작용에서 혹은 시간이 지남에 따라 변화되는 데이터를 다루는데 유용하다.
state는 컴포넌트에게 기억할 수 있게 한다.
--> 시간이 지남에 따라 변화될 것이라고 생각되는 컴포넌트 데이터를 추적하는데 state를 쓴다.
예시로, cat cate에서 두마리의 배고픈 고양이가 있고 시간이 지남에 따라 허기의 상태가 달라질 것임. 밥주기 버튼을 누르면 배고픈 고양이가 배불러지는 상태로 변경된다.
컴포넌트에 state를 추가하는 방법은 React's useState Hook을 부르는 것이다. Hook 이란 함수가 React 의 특징으로 채여지는 것. 예를 들어 useState는 함수 컴포넌트에 state를 추가하는 Hook이다.
// useState를 import한다.
import React, {useState} from 'react';
import {Button, Text, View} from 'react-native';
type CatProps = {
name: string;
};
const Cat = (props: CatProps) => {
/* 시간이 지남에 따라, 혹은 사용자와의 상호작용을 통해 변화될 것이라고 생각되는 데이터에 useState
useState는 문자열, 숫자, Boolean, 배열, Object 어느 데이터라도 추적하는데 사용된다.
useState는 초기 값으로 상태 변수를 만드는데, 여기서 isHungry라는 상태변수의 초기 값은 true이다.
어떻게 이름을 짓는 상관 없는데, 아래의 패턴으로 하면 편리하다.
[<getter>, <setter>] = useState(<initialValue>)
useState를 통해 isHungry 라는 상태 변수를 만든다. */
const [isHungry, setIsHungry] = useState(true);
return (
<View>
<Text>
I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
</Text>
<Button
//Button에 onPress라는 Prop을 줘, 누구든 버튼을 누르면 onPress가 fire하고, setIsHungry(false)를 부른다.
onPress={() => {
setIsHungry(false);
}}
// isHungry가 false면 Button의 disabled prop이 true가 되어 타이틀이 바뀐다.
disabled={!isHungry}
title={isHungry ? 'Give me some food, please!' : 'Thank you!'}
/>
</View>
);
};
const Cafe = () => {
return (
<>
<Cat name="Munkustrap" />
<Cat name="Spot" />
</>
);
};
export default Cafe;
※ isHungry가 const임에도 재할당이 가능하다. state-setting function이 불러질 때 컴포넌트가 다시 랜더링되고, Cat function이 다시 실행된다.