https://reactjs-kr.firebaseapp.com/docs/installation.html
기존의 뷰 프로세스 [CSR]
1. 요청 -> view(html) -> 화면을 전달하면 브라우저가 렌더링 [전체 변경]
2. view -> 자바스크립트의 비동기 요청 -> ajax를 통해 부분 변경-> json으로 응답 -> 응답받은 데이터를 이용해 렌더링 [부분 변경]
3. 복잡한 화면일수록 부분 변경이 어렵다. [성능과 구현 측면에서]
[SSR]
-> 부분변경 x -> ajax -> html -> 그림그리기
리액트
: ajax -> 데이터 변경감지 -> UI가 자동 업데이트 [옵저버 패턴]
*npm, npx
(1) npm 프로젝트별로 라이브러리 관리 / 모든 프로젝트가 공유하도록 사용도 가능 (여러 버전 사용 불가능 -> 단일 버전만 가능)
(2) npx 라이브러리 존재시 공유 -> 실행 후, 삭제
npx create-react-app my-app
cd my-app
npm start
ESLint / Prettier / ReactJs code snippets
prettier 설정
{
"singleQuote": false,
"semi": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
1) 실행 과정 - index.html을 구동 시키기 위한 과정 = SPA(Single Page Applicaiton)
-> a태그 사용불가 (클릭할 때 브라우저가 해당 URL로 이동하면서 전체 페이지를 다시 로드하기 때문에)
[ 태그 사용을 제한하는 이유는 페이지 리로드로 인한 성능 저하와 상태 유실을 방지
대신, 자바스크립트 기반 라우팅 라이브러리(React Router)를 사용하여 URL 변경과 동적 콘텐츠 로딩을 처리]
더보기
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}
package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
-> index.tsx 실행
index.tsx
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
</React.StrictMode>
);
-> rendering
public/index.html
* Document 클래스 메서드
1) queryselector-> 선택자 '#'은 ID
2) getelementbyid-> ID요소 가져오기
2) jsx 문법
*tsx -> js로 변환 후 렌더링
: JavaScript 및 TypeScript 코드에서 HTML과 같은 구문을 사용하여 UI 구성 요소를 작성할 수 있게 하는 확장 문법
-> js에 html 주입
[React.js (라이브러리) / Next.js (프레임워크)]
타입 | 라이브러리 | 프레임워크 |
---|---|---|
기본 렌더링 방식 | 클라이언트 사이드 렌더링(CSR) | 서버사이드 렌더링(SSR) 및 정적 사이트 생성(SSG) 지원 |
라우팅 | React Router 등 외부 라이브러리 필요 | 파일 기반 라우팅 지원 |
데이터 페칭 | 클라이언트 사이드에서 주로 처리 | SSR, SSG, 클라이언트 사이드 모두 지원 |
API 라우트 | 없음 (외부 서버 필요) | 내장된 API 라우트 지원 |
설치 및 설정 | 필요한 라이브러리들을 별도로 설정 | 기본 설정이 포함된 일체형 프레임워크 |
코드 스플리팅 | Webpack 등 설정 필요 | 기본 제공 |
CSS 지원 | 외부 라이브러리 사용 (예: styled-components, Emotion) | 기본적으로 CSS 및 Sass 지원 |
jsx: js에 html 넣는 방법 -> function App() { JSX 문법 }
function App() {
return (
//1)
// <div className="App">
// <header className="App-header">
// <img src={logo} className="App-logo" alt="logo" />
// <p>
// Edit <code>src/App.tsx</code> and save to reload.
// </p>
// <a
// className="App-link"
// href="https://reactjs.org"
// target="_blank"
// rel="noopener noreferrer"
// >
// Learn React
// </a>
// </header>
// </div>
<div>
Hello
</div>
);
}
(1) react는 하나의 태그만 리턴 -> 하나의 태그 안에 모두 삽입
-> return 시에 하나의 Dom만 리턴
(2) 변수의 위치 (변수 스코프)
-> 변수 선언 : let/const만 사용 [var의 스코프는 일반적으로 예상가능하지 않음]
(3) if사용 불가 -> 삼항연산자로 대신 가능 (조건?true:false)
-> '==' : 값 동등 체크, '===' : 값+타입 동등 체크
(4)조건부 렌더링 참일때만 '&&' (조건 && true)
-> 참일때만 출력
(5) 리턴이 한줄일 떄와 한줄 초과일 때 괄호 유무의 차이
-> 한줄일 때는 괄호 생략 가능
(6) js에서 변수에 선언만 할 경우 -> undefined (NULL이 아님)
(7) css 디자인
- 내부
- 외부
- 라이브러리 사용 (부트스트랩, component-style)
3) useState
: 상태값 변경시 렌더링 -> 상태값이 아니면 변경되어도 화면상에선 바뀌지않음
더보기
주의사항
- 비동기 상태 업데이트: setState 함수는 비동기로 작동할 수 있으며, 즉시 상태가 업데이트되지 않을 수 있습니다. 따라서 상태가 즉시 반영되지 않는 경우가 있을 수 있습니다.
- 이전 상태 기반 업데이트: 상태 업데이트가 이전 상태 값에 의존하는 경우, 콜백 함수를 사용하는 것이 좋습니다.
- jsxconst increment = () => { setCount(prevCount => prevCount + 1); };
- 코드 복사
- 객체 상태 업데이트: 상태가 객체인 경우, 전체 객체를 복사하고 수정해야 합니다.
- ...prevUser: 이전 상태를 복사합니다.
- { ...prevUser, name: 'Jane' }: 복사한 상태에 name 속성을 변경합니다.
- jsxconst [user, setUser] = useState({ name: 'John', age: 30 }); const updateName = () => { setUser(prevUser => ({ ...prevUser, name: 'Jane' })); };
- 코드 복사
요약
- useState 훅은 상태 값을 관리하는 데 사용됩니다.
- useState 훅은 현재 상태 값을 읽는 변수와 상태 값을 업데이트하는 함수를 반환합니다.
- 상태 값을 업데이트할 때는 set 접두어를 사용하는 함수(setCount, setUser 등)를 호출합니다.
- 상태 업데이트는 비동기로 작동할 수 있으며, 이전 상태에 기반한 업데이트는 콜백 함수를 사용하는 것이 좋습니다.
4) sub 컴포넌트
React 컴포넌트의 종류와 이에 대한 약어들은 다양하며, 주로 코드 템플릿이나 스니펫에서 사용됩니다. 여기에 각 컴포넌트의 종류와 해당 약어들을 소개합니다.
함수형 컴포넌트 (Functional Components)
- React Stateless Component (RSC)
- 상태를 관리하지 않는 함수형 컴포넌트입니다.
import React from 'react'; const RSC = () => { return <div>Hello, World!</div>; }; export default RSC;
- React Stateless Component with Props (RCSP)
- props를 받아 렌더링하는 상태가 없는 함수형 컴포넌트입니다.
import React from 'react'; const RCSP = (props) => { return <div>{props.message}</div>; }; export default RCSP;
- React Functional Component (RFC)
- 기본적인 함수형 컴포넌트를 의미합니다.
import React from 'react'; const RFC = () => { return <div>Hello, World!</div>; }; export default RFC;
- React Functional Component with Props (RFCP)
- props를 사용하는 함수형 컴포넌트입니다.
import React from 'react'; const RFCP = ({ message }) => { return <div>{message}</div>; }; export default RFCP;
클래스형 컴포넌트 (Class Components)
더보기
- React Class Component (RCC)
- 상태와 생명주기 메서드를 사용할 수 있는 클래스형 컴포넌트입니다.
import React, { Component } from 'react'; class RCC extends Component { constructor(props) { super(props); this.state = { count: 0, }; } render() { return ( <div> <p>{this.props.message}</p> <p>Count: {this.state.count}</p> </div> ); } } export default RCC;
- React Class Component with Props (RCCP)
- props를 사용하는 클래스형 컴포넌트입니다.
import React, { Component } from 'react'; class RCCP extends Component { render() { return <div>{this.props.message}</div>; } } export default RCCP;
- React Pure Component (RPC)
- PureComponent를 상속받아 shouldComponentUpdate를 자동으로 구현하는 클래스형 컴포넌트입니다.
import React, { PureComponent } from 'react'; class RPC extends PureComponent { render() { return <div>{this.props.message}</div>; } } export default RPC;
Hook 기반 컴포넌트
- React Hook Component (RHC)
- Hook을 사용하는 함수형 컴포넌트입니다.
import React, { useState } from 'react'; const RHC = () => { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default RHC;
- React Hook Component with Props (RHCP)
- Hook과 props를 사용하는 함수형 컴포넌트입니다.
import React, { useState } from 'react'; const RHCP = ({ initialCount }) => { const [count, setCount] = useState(initialCount); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default RHCP;
고차 컴포넌트 (Higher-Order Components)
- React Higher-Order Component (HOC)
- 다른 컴포넌트를 감싸는 컴포넌트입니다.
import React from 'react'; const withEnhancement = (WrappedComponent) => { return class extends React.Component { render() { return <WrappedComponent {...this.props} />; } }; }; export default withEnhancement;
컨텍스트 기반 컴포넌트
- React Context Provider (RCP)
- Context API의 Provider를 사용하는 컴포넌트입니다.
import React, { createContext, useState } from 'react'; export const MyContext = createContext(); const RCP = ({ children }) => { const [value, setValue] = useState('default value'); return ( <MyContext.Provider value={{ value, setValue }}> {children} </MyContext.Provider> ); }; export default RCP;
- React Context Consumer (RCC)
- Context API의 Consumer를 사용하는 컴포넌트입니다.
import React from 'react'; import { MyContext } from './RCP'; const RCC = () => { return ( <MyContext.Consumer> {({ value, setValue }) => ( <div> <p>{value}</p> <button onClick={() => setValue('new value')}>Change Value</button> </div> )} </MyContext.Consumer> ); }; export default RCC;
이와 같이 다양한 유형의 React 컴포넌트가 있으며, 각 유형의 컴포넌트는 특정 목적과 사용 사례에 맞게 설계되었습니다. 이러한 약어들은 개발자들이 코드 템플릿을 빠르게 생성하고, 코드의 가독성을 높이는 데 도움을 줍니다.
* push는 불변
-> 레퍼런스 변경 : filter, map, concat, slice, 정규연산자
Hooks, Flux패턴 , Redux 예시
1. Hooks
사용 예시: 간단한 상태 관리와 부수 효과 처리
- 예제: 사용자 입력 폼 관리
import React, { useState, useEffect } from 'react';
function UserForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
useEffect(() => {
console.log('Name or email changed');
}, [name, email]);
return (
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<p>Name: {name}</p>
<p>Email: {email}</p>
</div>
);
}
export default UserForm;
설명: 여기서는 useState
를 사용하여 간단한 상태(이름과 이메일)를 관리하고, useEffect
를 사용하여 상태 변경 시 부수 효과를 처리합니다. 이 패턴은 단일 컴포넌트 내에서 간단한 상태 관리에 적합합니다.
2. Redux에서 사용하는 Flux 패턴
사용 예시: 복잡한 애플리케이션의 데이터 흐름 관리를 위한 정형화된 패턴
- 예제: 기본적인 Flux 패턴의 구조
// actions.js
export const addAction = (item) => ({
type: 'ADD_ITEM',
payload: item,
});
// dispatcher.js
import { Dispatcher } from 'flux';
export const AppDispatcher = new Dispatcher();
// store.js
import { EventEmitter } from 'events';
import { AppDispatcher } from './dispatcher';
let items = [];
class ItemStore extends EventEmitter {
getItems() {
return items;
}
addItem(item) {
items.push(item);
this.emit('change');
}
}
const store = new ItemStore();
AppDispatcher.register((action) => {
switch (action.type) {
case 'ADD_ITEM':
store.addItem(action.payload);
break;
default:
break;
}
});
export default store;
// view.js
import React, { useState, useEffect } from 'react';
import store from './store';
import { addAction } from './actions';
import { AppDispatcher } from './dispatcher';
function ItemList() {
const [items, setItems] = useState(store.getItems());
useEffect(() => {
store.on('change', () => {
setItems(store.getItems());
});
}, []);
const addItem = () => {
AppDispatcher.dispatch(addAction('New Item'));
};
return (
<div>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={addItem}>Add Item</button>
</div>
);
}
export default ItemList;
설명: Flux 패턴을 사용하여 액션, 디스패처, 스토어, 뷰의 구조를 구성합니다. 이 패턴은 상태와 관련된 모든 변경 사항을 체계적으로 관리하여 복잡한 애플리케이션의 데이터 흐름을 예측 가능하게 합니다.
3. Redux
사용 예시: 중앙 집중화된 상태 관리와 비동기 작업 처리
- 예제: Todo 애플리케이션
// actions.js
export const ADD_TODO = 'ADD_TODO';
export const addTodo = (text) => ({
type: ADD_TODO,
payload: text,
});
// reducers.js
import { ADD_TODO } from './actions';
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
default:
return state;
}
};
export default rootReducer;
// store.js
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer);
export default store;
// TodoList.js
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { addTodo } from './actions';
function TodoList() {
const [input, setInput] = useState('');
const todos = useSelector((state) => state.todos);
const dispatch = useDispatch();
const handleAddTodo = () => {
dispatch(addTodo(input));
setInput('');
};
return (
<div>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Add todo"
/>
<button onClick={handleAddTodo}>Add Todo</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
}
export default TodoList;
설명: Redux를 사용하여 중앙 집중화된 상태 관리와 액션 및 리듀서를 통해 상태 변경을 예측 가능하게 합니다. Redux의 미들웨어를 활용하여 비동기 작업을 처리할 수 있습니다.
사용하는 이유
- Hooks로 간단한 컴포넌트 상태와 부수 효과를 관리하고,
- Redux로 중앙 집중화된 상태 관리와 비동기 작업을 처리합니다.
- Flux 패턴으로 데이터 흐름을 체계적으로 관리
- 모든 컴포넌트가 props 없이 state를 직접 사용(읽기) 가능
- state에 대한 의미있는 메서드를 미리 정의
이러한 조합은 애플리케이션의 규모와 복잡성에 따라 적절한 도구를 선택하여 효율적으로 상태를 관리하고, 유지보수성을 높입니다.
React Hooks
1. useEffect
(1) 최초 실행 시 -> 최초 의존성 배열을 다운받아야 함 -> 상태변수가 되어야함
(2) 의존성 배열이 변경되는 시점
2. useMemo
(1) 메모리제이션
(2) return에서 한 상태변수의 상태변경에 의해 다른 상태변수까지 상태변경되었다고 인지되는 것 방지
(3) 두 개의 인자 : 1) 계산할 값 또는 함수, 2) 의존성 배열
-> 의존성 배열에 포함된 값이 변경될 때만 게산이 다시 수행
3. useRef
(1) 디자인 변경
(2) DOM 객체에 접근해 스타일 변경
const myRef = useRef<HTMLDivElement>(null);
<div ref={myRef}>박스</div>
//Ref를 배열로, createRef라는 동적으로 만든 배열 리턴 -> myref를 배열로 만들어주는 메서드
let myRefs = Array.from({ length: list2.length }).map(() =>
createRef<HTMLHeadingElement>(),
);
<div>
{list2.map((user, index) => (
//useRef 배열 생성 필요 -> createRef
<h1 ref={myRefs[index]}>{user.name}</h1>
))}
</div>
'JavaScript > React.js' 카테고리의 다른 글
리액트2 - 스타일 (0) | 2024.08.05 |
---|