티스토리 뷰
Redux
pub-sub model(구독패턴)을 구현한 라이브러리이다.
(어떤 객체가 하나 있을 때 이 객체가 변경되면 구독한 함수를 호출해서 변경될 때마다 알려줌)
웹앱
어떠한 데이터를 어떠한 모양으로 어디에 배치하는지가 중요하다, 그 이후는 HTML과 CSS가 다 처리한다.
데이터는 API호출을 통해 비동기적으로 가져온다. 비동기로 가져오다보면 예외상황이 발생할 수 있으므로 각 경우에 따라 대응되는 코드들이 추가된다.
웹앱 개발시 코드를 빠르게 찾고 고칠 수 있는 구조를 연구하여 나온 것 중에 하나가 리액트.
"어떤것이 좋은 아키텍쳐인가?"
→ 결국 같은 것끼리 묶고, 다른 것들은 분리하는 것.(지식의 수준/역량에 따라서 차이가 발생할 수 있음. 데이터의 복잡도에 따라도 달라질 수 있음)
→ 이름만 잘 지어도 70%는 먹고들어간다. 구조가 읽기 쉬워지니까.
React
리액트의 원리
리액트의 원리를 이해하기 위해 간단하게 만들어BOJA
//index.js
const list = [
{ title: "React에 대해 알아봅시다." },
{ title: "Recux에 대해 알아봅시다." },
{ title: "TS에 대해 알아봅시다." }
];
const rootElement = document.getElementById("root");
function app() {
rootElement.innerHTML = `
<ul>
${list.map((item) => `<li>${item.title}</li>`).join("")}
</ul>
`;
}
app();
위의 코드는 바깥의 영향을 받을 수 밖에 없으므로 아래와 같이 수정한다.
*바깥에 영향을 받지 않는 함수를 순수함수라고 한다.
const list = [
{ title: "React에 대해 알아봅시다." },
{ title: "Recux에 대해 알아봅시다." },
{ title: "TS에 대해 알아봅시다." }
];
const rootElement = document.getElementById("root");
function app(items) {
rootElement.innerHTML = `
<ul>
${items.map((item) => `<li>${item.title}</li>`).join("")}
</ul>
`;
}
app(list);
위 코드에서는 rootElement에 접근해서, innerHTML로 직접 DOM에 코드를 주입한다.
실제 리액트에서는 Virtual DOM으로 좀 더 간단하게 처리할 수 있도록 해준다.
Virtual DOM
브라우저는 HTML 코드 문자열을 DOM tree로 만들어 다루기 쉽게 만든다.
하지만 앱의 규모가 커지면서 이 DOM tree를 다루는 것이 더 복잡해짐에따라 real DOM을 다루는건 조금 구시대적이 되었다.
그래서 같은 컨셉으로, 리액트는 (DOM에 직접 접근하면 복잡하니) Virtual DOM(=VDOM)을 만들어서 좀 더 쉬운 구조로 만들도록 했다.
VDOM과 JS 사이를 쉽게 구조화(?) 하기위해 나온것이 바로 JSX
virtual DOM은 아마도 이런 구조로 생겼을 것이다. 제일 상위에 최상위 컴포넌트가 있을것이고, 그래서 VDOM은 한개가 존재할 수 있는 것이다.
{
type: "ul",
props: {},
children: [
{
type: "li",
props: { className: "item" },
children: "React"
},
{
type: "li",
props: { className: "item" },
children: "Redux"
},
{
type: "li",
props: { className: "item" },
children: "TypeScript"
}
]
};
리액트의 구조
React와 React DOM을 import하고 컴포넌트를 render함수로 실행해준다.
import React from "react";
import ReactDOM from "react-dom";
function App() {
return <h1>1</h1>;
}
ReactDOM.render(<App />, document.getElementById("root"));
참고) 아래와 같이 리턴해 주는 부분이 JSX문법이다. 바벨에서 확인해보면 Virtual DOM을 만드는 함수 호출되는걸 알 수 있다.
function App() {
return (
<div>
<h1>Hello?</h1>
<ul>
<li>React</li>
<li>Redux</li>
<li>TypeScript</li>
</ul>
</div>
);
}
이렇게 컴포넌트를 더 만들 수 있다. StudyList라는 이름으로 컴포넌트를 생성함으로써 좀 더 이해하기 쉽고, 관리가 수월해지게 된다.
function StudyList() {
return (
<ul>
<li className="item">React</li>
<li className="item">Redux</li>
<li className="item">TypeScript</li>
</ul>
);
}
function App() {
return (
<div>
<StudyList />
</div>
);
}
*HTML과 달리 class가 아니라 className이라고 쓰는 이유는 class가 예약어이기 때문이다.
function StudyList(props) {
return (
<ul>
<li className="item">React</li>
<li className="item">Redux</li>
<li className="item">TypeScript</li>
</ul>
);
}
function App() {
return (
<div>
<StudyList item="abc"/>
</div>
);
}
컴포넌트에 속성을 전달할 때는 위와 같이 props를 이용하는데, 컴포넌트는 함수이기 때문에 props 외에 다른 방법으로 데이터를 전달 할 수는 없다.
React 내부에 존재하는 createElement 함수를 살펴보자.
React.createElement(type, props = {}, ...children) {
return { type, props, children }
}
//실제 코드 실행시 아래와 같이 실행이 되는 것
React.createElement('ul', {}, createElement('li', {}, 'React'));
요렇게 Render()가 객체를 쫒아가면서 만들어진 VDOM을 realDOM으로 converting 할 것이다.
바벨 기능 중에 아래와 같은 방식으로 작성을 하면, 컴파일 타임에 작성한 문법을 찾아서 변환해주는 것이 있다.
(요즘은 브라우저가 직접 실행할 수 없으므로 컴파일 타임이 생김. 컴파일타임인지 런타임인지 알고 있어야한다.)
/* @jsx createElement */
function App() {
...
}
위와 같이 작성하면 컴파일시 이렇게 된다.
function createElement( App(), {}, createElement(...)}
이 때 중요한 점!
바벨은 대문자 소문자 처리방식이 다르다.
소문자 예) <ul> → 문자열로 처리
대문자 예) <App /> → 함수로 처리
그래서 사용자 컴포넌트는 반드시 대문자로 시작해야하는 것.
다음으로 render element를 구현한다. 역할은 virtual DOM 객체를 리턴하는 것이다.
function renderElement(node) {
if (typeof node === "string") {
return document.createTextNode(node);
}
const el = document.createElement(node.type);
//자식들 렌더링
node.children.map(renderElement).forEach((element) => {
el.appendChild(element);
}); //재귀호출함
return el;
}
이제 화면에 그려줄 render 함수를 만들어보자.
function render(vdom, container) {
container.appendChild(renderElement(vdom));
}
*완성된 코드*
/* @jsx createElement */
function renderElement(node) {
if (typeof node === "string") {
return document.createTextNode(node);
}
const el = document.createElement(node.type);
//자식들 렌더링
node.children.map(renderElement).forEach((element) => {
el.appendChild(element);
}); //재귀호출함
return el;
}
function render(vdom, container) {
container.appendChild(renderElement(vdom));
}
function createElement(type, props = {}, ...children) {
//자식은 여러개 올 수 있으니까
if (typeof type === "function") {
return type.apply(null, [props, ...children]);
}
return { type, props, children };
}
function Row(props) {
return <li>{props.label}</li>;
}
function StudyList(props) {
return (
<ul>
<Row label="음메" />
<li className="item">React</li>
<li>Redux</li>
<li>TypeScript</li>
</ul>
);
}
function App() {
return (
<div>
<StudyList item="abc" />
</div>
);
}
render(<App />, document.getElementById("root"));
이것이 바로 리액트가 돌아가는 방식이다.
실제 리액트에서는 render안에서 실제 DOM과 비교해서 바뀐부분만 반영된다.
컴포넌트
클래스 컴포넌트
클래스 형태의 컴포넌트는 아래와 같다.
class Hello extends React.Component{
constructor(props) {
super(props) //받은 props를 react에 전달
}
render() {
//반드시 렌더함수를 구현해야함.
return (
<p>Hi</p>
)
}
}
//리액트 내부적으로 아래를 실행해줌
//const hello = new Hello();
//hello.render();
function App() {
return (
<div>
<h1>상태</h1>;
<Hello />
</div>
)
}
클래스형 컴포넌트는 객체 안에서 값을 유지하고 있을 수 있었기 때문에 자체적으로 상태를 자연스럽게 가질 수 있다.
또한 함수형 컴포넌트는 라이프사이클이 없는 반면, 클래스 컴포넌트는 필요한 부분만 호출을 하여 사용하기 때문에 lifecycle methods가 존재한다.
(예: componentDidMount 등)
함수형 컴포넌트
함수형은 지금까지 위에서 써왔던 형태의 컴포넌트이고, 클래스 컴포넌트보다 간단하고 선언적이다.
초창기 리액트에서 함수형 컴포넌트는 호출시마다 초기화되어 상태를 가질 수 없었다.
그러나 Hooks가 생기면서 함수형 컴포넌트에서도 상태를 가질 수 있게 되었다.
Hooks
함수형 컴포넌트에서 상태를 가지게 할 수 있는 스펙이다.
useState()
리액트가 제공하는 함수로 기본적으로 배열을 리턴한다.
배열의 첫번째 값은 상태, 두번째 값은 dispatcher 함수가 된다.
function App() {
const [ counter, setCounter] = useState(1);
return (
<div>
<h1 onClick={() => setCounter(coutner + 1 )}>상태 { counter }</h1>
</div>
);
}
함수를 호출해도 counter가 리셋되지 않고 값을 유지할 수 있는 이유:
(함수는 컴포넌트를 리턴한다는 것을 리액트가 알고 있으니) hook 계열의 함수를 호출하면 연관된 Hook 전역 배열에 초기값과 값의 index를 담는다. 이후 변경이 발생하면 저장되어있는 값을 가지고 변경 값을 리턴한다.
훅 사용시 중요한 것!
*반복문, 조건문, 중첩된 함수에서 hook을 사용하면 안된다.*
*나중에 볼 것
Rodrigo Pombo
Also known as pombo, pomber, pombus, pombex, or any /pomb[a-z]+/ match. I write code, write about writing code, sometimes talk about it, usually tweet about it.
pomb.us
stackoverflow.com/questions/46989454/class-vs-classname-in-react-16/46991278
class vs className in React 16
I saw that React 16 allows for attributes to be passed through to the DOM. So, that means 'class' can be used instead of className, right? I'm just wondering if there are advantages to still using
stackoverflow.com
'React' 카테고리의 다른 글
[우아한테크러닝 3기 : React&TypeScript] 5일차 - 미들웨어 (0) | 2020.09.15 |
---|---|
[우아한테크러닝 3기 : React&TypeScript] 4일차 - 컴포넌트 디자인, 비동기 (0) | 2020.09.10 |
[우아한테크러닝 3기 : React&TypeScript] 2일차 - 함수, Redux (0) | 2020.09.03 |
[우아한테크러닝 3기 : React&TypeScript] 1일차 - Overview (0) | 2020.09.01 |
리액트 ref로 DOM에 접근하기 (0) | 2020.02.16 |
- Total
- Today
- Yesterday
- sort()
- Props
- React
- 1day1algorithm
- 멀티프로그래밍
- 프로그래머스
- greedyAlgorithm
- Typescript
- Webpack
- reduce()
- javascript
- Algorithm
- 타입스크립트
- sort
- Array
- 배열
- 리액트
- js
- 컴퓨터공학
- 구간합
- 시분할시스템
- OS
- 자바스크립트
- 우아한테크러닝
- 배치처리시스템
- redux-saga
- 알고리즘
- 웹팩
- 운영체제
- 자료구조
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |