[Day 41] React Advance(JSX more, Static Type Check, Ref, Board Exercise)
앞으로의 Curriculum
- VS CODE 에서의 리액트 코딩
- create-react-app
- CSS 구조적 코딩 (CSS의 스코프를 만들어주는)
- BEM -> CSS 모듈
- HTML5 History API + React Router
- SPA에 Routing을 잡아주고 각각의 페이지로 동작하도록
- 상태와 표현의 분리
- Container Component (상태만 관리)
- Presentational Component (그리기만)
- 테스트를 위한 도구인 Story Board
- React에서 SEO 관리를 위한 기술
- SSR (Server Side Rendering)
- Next.js
React Advance
JSX 더 알아보기
React 엘리먼트의 타입 지정하기
JSX 태그의 첫 부분은 React 엘리먼트의 타입을 결정한다.
대문자로 시작하는 타입은 해당 JSX 태그가 React 컴포넌트임을 가리킨다.
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
위와 같이 컴포넌트를 불러오는 JSX 표현을 사용하려면 해당 컴포넌트가 반드시 스코프 내에 존재해야 한다.
React가 스코프 안에 있어야 한다.
JSX는 React.createElement
를 호출하는 코드로 컴파일 되기 때문에 React 라이브러리가 JSX 코드의 스코프 안에 항상 있어야만 한다.
import React from 'react';
import CustomButton from './CustomButton';
function WarningButton() {
// return React.createElement(CustomButton, {color: 'red'}, null);
return <CustomButton color="red" />;
}
JSX 타입을 위한 점 표기법
import React from 'react';
const MyComponents = {
DatePicker: function DatePicker(props) {
return <div>Imagine a {props.color} datepicker here.</div>;
}
}
function BlueDatePicker() {
return <MyComponents.DatePicker color="blue" />;
}
객체의 속성 값으로 컴포넌트가 올 수 있다.
사용자 정의 컴포넌트는 대문자로 시작해야 한다.
엘리먼트 타입이 소문자로 시작할 경우, DOM의 내장 컴포넌트(태그)를 의미하며 문자열의 형태로 컴파일 되면서 React.createElement
로 전달된다.
대문자로 시작하는 타입은 하나의 변수(컴포넌트)로 React.createElement
에 인수로 전달된다.
실행 중에 타입 선택하기
prop을 가지고 컴포넌트를 선택해서 센더링해야 하는 경우
import React from 'react';
import { PhotoStory, VideoStory } from './stories';
const components = {
photo: PhotoStory,
video: VideoStory
};
function Story(props) {
// 올바른 사용법입니다. 대문자로 시작하는 변수는 JSX 타입이 될 수 있습니다.
const SpecificStory = components[props.storyType];
return <SpecificStory story={props.story} />;
}
JSX 안에서 prop 사용하기
Props의 기본값은 “True”
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
속성 펼치기
const Button = props => {
const { kind, ...other } = props;
const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
return <button className={className} {...other} />;
};
const App = () => {
return (
<div>
<Button kind="primary" onClick={() => console.log("clicked!")}>
Hello World!
</Button>
</div>
);
};
JSX에서 자식 다루기
JSX를 자식으로 사용하기
<MyContainer>
<MyFirstComponent />
<MySecondComponent />
</MyContainer>
React 컴포넌트는 엘리먼트로 이루어진 배열을 반환할 수도 있다.
render() {
// 별도의 엘리먼트로 감싸줄 필요가 없습니다!
return [
// 키를 잊지 마세요 :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
함수를 자식으로 사용하기
// Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
let items = [];
for (let i = 0; i < props.numTimes; i++) {
items.push(props.children(i));
}
return <div>{items}</div>;
}
function ListOfTenThings() {
return (
<Repeat numTimes={10}>
{(index) => <div key={index}>This is item {index} in the list</div>}
</Repeat>
);
}
- 여는 태그와 닫는 태그 사이의 문자열 또는
{} 안의 표현식
은props.children
으로 컴파일 된다.
진리값, null, undefined는 무시된다.
true
, false
, null
, undefined
는 유효한 자식이다. 다만, 렌더링되지는 않는다.
이러한 성질을 이용해 React 엘리먼트를 조건부로 렌더링할 수 있다.
<div>
{showHeader && <Header />}
<Content />
</div>
(주의!) React는 false
는 렌더링하지 않지만 falsy
는 렌더링한다.
0
이나 NaN
같은 falsy
값들은 렌더링 된다.
// props.messages.length가 0이라면 렌더링 된다.
<div>
{props.messages.length &&
<MessageList messages={props.messages} />
}
</div>
(활용) 렌더링되지 않는 true
, false
, null
, undefined
를 렌더링하고 싶다면 문자열로 변환한 뒤 사용하면 된다.
<div>
My JavaScript variable is {String(myVariable)}.
</div>
정적 타입 체크
정적 타이핑 vs 동적 타이핑
정적 타이핑 언어
코드를 실행하기 전 컴파일 과정에서 타입을 검사한다. (ex. Java, C, C++, C#, Swift, Kotlin …)
실행 전에도 타입 관련 버그를 발견할 수 있다.
동적 타이핑 언어
실행 시간에 타입을 검사한다. (ex. JavaScript, Python, Ruby …)
타입에러는 코드를 실행시킬 때 발생한다.
실행 전에는 타입 관련 버그를 발견하기 어렵다는 단점이 있다.
이러한 문제를 해결하기 위해 자바스크립트에 컴파일 과정 중 타입 체크 기능을 추가한 확장 언어가 존재한다. (ex. TypeScript, Flow …)
내가 선언한 변수들의 상태를 관리할 수 있다. (코드를 읽기가 쉬워진다.)
Ref와 DOM
Ref
는 render() 메소드에서 생성된 DOM 노드 혹은 React 엘리먼트 객체에 접근할 수 있도록 해준다.
Ref를 사용해야 하는 때
- 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때 (DOM API의 메소드를 사용할 수 밖에 없을 때)
- 명령형 애니메이션을 발동시킬 때
- 서드파티 DOM 라이브러리를 통합할 때 (DOM 객체에 직접 작용하는 라이브러리를 사용해야 할 때)
- DOM 객체를 가리키고 싶을 때
Ref 생성하기
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
Ref 사용하기
React 엘리먼트에 ref가 넘겨지면 current
속성을 통해 해당 노드에 접근할 수 있다.
const node = this.myRef.current;
(중요!) ref의 값은 노드의 유형에 따라 달라진다.
- HTML 엘리먼트에
ref
어트리뷰트가 사용되면 ref의current
속성은 DOM 엘리먼트 객체를 가리킨다. - 클래스 컴포넌트에
ref
어트리뷰트가 사용되면 ref의current
속성은 해당 컴포넌트로부터 생성된 인스턴스(public instance)를 가리킨다.
함수형 컴포넌트는 인스턴스를 가질 수 없기 때문에 ref 어트리뷰트를 사용할 수 없다.
게시판 실습
create-react-app
package bundler 도구인 Webpack
과 JS Compiler인 Babel
을 미리 셋팅해놓은 프로젝트를 만들어주는 npm package
// npx는 npm에서 패키지를 받아서 바로 실행시키는 명령어
npx create-react-app fds-bbs
cd fds-bbs
npm start
Folder Structure
my-app/
README.md
node_modules/
package.json
public/
index.html
favicon.ico
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
public
folder 내부의 파일은 build 과정을 거치지 않고 사용자에게 전달된다.
src
folder 내부의 파일은 build 과정(transpiling)을 거친 후 사용자에게 전달된다.
Supported Browsers and Features
IE 9, 10, 11 에서는 polyfill 을 통해 사용할 수 있다.
IE8 이하는 지원하지 않는다.
Life-Cycle
componentDidMount() {}
componentDidMount 함수가 비동기함수여도 데이터를 다 받아온 뒤에 componentDidMount 함수가 실행되는 것은 아니다.
해당 컴포넌트가 그려질 때 무조건 componentDidMount 함수가 실행되면서 한 번 그려지고, 그 안에 setState()가 있다면 상태를 바꾸고 또 다시 그린다.
댓글남기기