리액트는 자바스크립트를 이용한 프론트앤드개발을 더 편리하게 해주기 위한 라이브러리다
Virtual DOM을 활용하여 업데이트 해야하는 DOM 요소를 찾아서 해당 부분만 업뎃함
MPA(멀티 페이지 어플리케이션) 아키텍처는 페이지마자 서버에 해당 페이지의 HTML파일을 요청하고,
이를 브라우저가 응답으로 받아 유저가 볼수 있도록 그려주는 구조였다.
SPA는 서버에서 HTML페이지들을 일일이 다운로드하는 것이 아니라,
하나의 마크업 HTML 파일을 받아서 클라이언트에서 데이터를 직접 로딩해 동적으로 화면을 표시함
Virtual DOM -> 가상돔이라고 한다.
HTML 마크업 구조를 자바스크립트로 조작이 가능한 객체 형태(Object 형태)로 모델링한 것을 DOM이라고 한다.
(Document Object Modeling)
DOM은 웹페이지를 우리가 사용하는 js와 같은 프로그래밍 언어와 연결해주어 화면에 그려진 ui요소를 조작할 수 있게 도와준다.
웹페이지에 그려진 화면을 조작하기 위해서는 DOM이라는 것을 조작해야 하는데,
우리가 어떤 DOM요소를 변경하게 되면 브라우저는 새롭게 변경된 DOM을 토대로 새롭게 화면을 그리는것
브라우저는 변화가 생기면 이 변화를 새롭게 표현하기 위해 어려가지 과정을 거치는데,
이때 가장 큰 연산비용이 드는 단계는 DOM의 요소 변화 이후, 요소들이 위치를 계산하는 레이아웃 단계다
가상DOM은 실제로 렌더링 되지는 않았지만, 실제 DOM구조를 반영한 상태로 메모리에 있는 가상의 DOM이다. 메모리에 있다는 것은 우리가 변수를 선언을 할 때, 값을 할당하면 메모리에 저장할 수 있다고 할 수 있는데 이렇게 DOM도 값으로 표현되어 메모리에 저장되어있다는 것을 알수 있다.
원래는 돔 조작을 하면 이는 바로 브라우저를 통해 여러가지 렌더링 단계를 거치게 되는데,
그냥 메모리상에 그냥 값으로 존재하는 가상DOM은 변경이 일어나도 이것이 브라우저 렌더링과 직접적으로 연결되어 있지 않다.
만약, 리엑트가 가상돔의 변화를 실제 돔에 적용하지 않는 한, 아무리 많은 조작이 가상돔에 일어나도 이는 브라우저에 렌더링을 일으키지 않는다.
원래 for문으로 10개의 돔 요소를 수정하는 것과 같은 변경사항을 ‘한번’에 묶어서 실제 돔에 반영을 하는데 이를 Batching이라고 한다.
LTS : 롱텀서포티즈 → 말그대로 오랜 기간 지원이 가능하다.
패키지 매니저 : 무수히 많은 서드파티 패키지들이 모여있는 집합소다.
여기에서 리액트를 만드는 패키지, 리액트를 프로그래밍 할 때 필요한 여러 패키지 다운받아 활용 가능
ex ) npm , yarn
터미널 창에
npm install -g yarn
라고 쳤더니, 에러남
그래서
sudo npm install --global yarn
라고 치니까 설치됌
CRA라는 도구를 활용해서 리액트 앱을 만들어 볼 것
씨알에이는 리엑트 프로젝트를 하기 위해 필요한 여러 프로그램을 자동으로 설치해주는 도구
yarn create react-app week-1
이렇게 하고, 파일이 어디 설치되있는지 몰라서 검색해씀 week-1이라고..
내 사용자 폴더에 만들어져 있네
리액트 실행 : vs code - 터미널 - new 터미널
npm start
누군가가 ‘컴포넌트'를 만들어보세요. 라고 하면 html 태그를 리턴하는 함수를 만들면 된다!!
// 반대로 다른곳에서 Export된 컴포넌트를 가져와 사용하는 경우엔 import를 해주면 됌
import logo from "./logo.svg";
import "./App.css";
// 컴포넌트를 만들땐 반드시 첫글자를 '대문자'로 해주어야 한다.
// 폴더명의 경우 소문자로 시작하는 카멜케이스로 작성해주어야 한다.
function App() {
// return문을 기준으로 하여 위쪽으로는 Js를 쓸 수 있는 영역
// return문 아래로는 html태그가 작성되는 영역
// 정확히는 html 문법을 그대로 사용하는 것은 아니고, jsx라고 리액트에서 html을 사용하기 위한 문법이 따로 있음
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>부트캠프 리액트 입문주차 시작!</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
// 컴포넌트를 외부에서 사용할 수 있도록 export를 해주어야 한다.
export default App;
> alert창 띄우는 퀴즈 푼 것
import React from "react";
function App() {
// <---- 자바스크립트 영역 ---->
const buttonEvent = () => {
alert("얼러트 창 뜨기!");
};
return (
/* <---- HTML/JSX 영역 ---->*/
<div
style={{
height: "100vh",
display: " flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
}}
>
{/* 이곳에 퀴즈를 위한 html 코드를 작성해 주세요 */}
<span>이것은 내가 만든 App 컴포넌트입니다.</span>
<button onClick={buttonEvent}>클릭!</button>
</div>
);
}
export default App;
>> 컴포넌트의 부모자식관계
// src/App.js
import React from "react";
function 할아버지() {
return <아들 />;
}
function 아들() {
return <손자 />;
}
function 손자() {
return <div>나는 손자입니다.</div>;
}
function App() {
return <할아버지 />;
}
export default App;
JSX 문법
JSX 는 html처럼 생겼지만, 엄연히 ‘바벨'이라는 라이브러리가 자바스크립트로 변환을 해주기때문에 js이다.
jsx는 무조건 1개의 엘리먼트만 반환할 수 있다!!!
이렇게 하나의 element로 만들어주어야 한다
jsx문법 안에서 자바스크립트 코드를 가져오려면, 반드시 { } 중괄호를 써야 한당
jsx문법에서는 class대신 className이라고 작성한다.
jsx문법에서는 HTML태그에 스타일을 직접 넣을 수 없다!!
>> Props
props는 부모 컴포넌트로부터 받아온 데이터이다.
// src/App.js
import React from "react";
function App() {
return <GrandFather />;
}
function GrandFather() {
return <Mother />;
}
// Mother가 가지고 있는 name을 Child로 내려주고 싶음
function Mother() {
const name = "홍부인";
// 이런식으로 자식 컴포넌트에 내려줄 수 있음
return <Child motherName={name} />;
}
// 이 props는 컴포넌트 간의 정보를 교류할 때 사용이 된다.
function Child(props) {
console.log("props", props);
return <div>연결 성공</div>;
}
export default App;
콘솔창에 찍어보면, motherName으로 key값에 ‘흥부인'이라는 데이터가 들어와있는걸 볼수있다.
⇒ object형식으로 내려온 걸 통해, props는 부모 컴포넌트에서 내려오는 모든 데이터를 칭하는 거라는 걸 알 수 있음
⇒ 실제로 object안에 있는 내가 원하는 데이터에 접근하기 위해서는, props.motherName으로 접근해야하는 것을 알 수 있다.
>> props는 오직 부모 component에서 자식 component 방향으로만 Props를 전달할 수 있다
// src/App.js
import React from "react";
function App() {
return <GrandFather />;
}
function GrandFather() {
return <Mother />;
}
// Mother가 가지고 있는 name을 Child로 내려주고 싶음
function Mother() {
const name = "홍부인";
// 이런식으로 자식 컴포넌트에 내려줄 수 있음
return <Child motherName={name} />;
}
// 이 props는 컴포넌트 간의 정보를 교류할 때 사용이 된다.
function Child(props) {
console.log("props : ", props);
console.log("props.motherName : ", props.motherName);
return <div>{props.motherName}</div>;
}
export default App;
grandFatherName 타고타고 내려가서 child에서 출력해보기
// src/App.js
import React from "react";
function App() {
return <GrandFather />;
}
function GrandFather() {
const name = "grandFatherName";
return <Mother grandFatherName={name} />;
}
function Mother(props) {
console.log("grandFatherName:", props.grandFatherName);
return <Child childGrandFatherName={props.grandFatherName} />;
}
function Child(props) {
console.log("props : ", props);
console.log("props.childGrandFatherName : ", props.childGrandFatherName);
return <div>{props.childGrandFatherName}</div>;
}
export default App;
props는 구조분해할당을 할 수 있다.
const props = { name1 : ‘hong’ }
const {name1} = props //props에 있는 keyName이 name1인 데이터를 꽂아준다.
console.log(name); // 출력값 : hong
// 객체구조분해
// Obj1의 오브젝트 타입이 있고, 거기 Key값들을 하나씩 빼올 수 있는데
const Obj1 = { obj1: "obj1콘텐츠", obj2: "obj2", obj3: "obj3" };
// 해당 Key네임을 작성해주고, 이렇게 옵줵 Obj1 를 꽂아주면, 해당 KeyName의 데이터가 꽂힌다.
const { obj3 } = Obj1;
console.log("타겟 : ", obj3);
props drilling 이란?
prop types ?
>>다른 방식으로 데이터 전달받기
>> state
state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.
useState는 state를 만들기 위해서 리액트에서 제공하는 hook(기능)이다.
[ ] 배열안에 value와 setValue가 나와있음
const [value, setValue] = useState(초기값);
첫번째 자리(value)에는 state의 이름이 들어간다.
두번째 자리(setValue)에는 set을 붙이고 그 state의 이름을 붙이는데, 첫번째에서 선언했던 state의 이름이다.
useState(a) ; : a에는 state의 원하는 초기값을 넣어주게 된다.
두번째 자리(setValue)는 state를 변경할 수 있는 함수고, 이 함수를 통해서만 state를 변경할 수 있다.
// src/App.js
import React, { useState } from "react";
function Child(props) {
//child가 받은 props에는 "할아부지이름가보"
return <div>{props.맘미가아들에게넘겨준이름}</div>;
}
function Mother(props) {
//props에 GrandFather에서 받아온 name이 담겨있고, ("김할아") 그걸 또 child에게 넘겨줬음
return (
<Child 맘미가아들에게넘겨준이름={props.할아부지가맘에게넘겨주는이름} />
);
}
function GrandFather() {
const [name, setName] = useState("할아부지이름가보"); // state를 생성
return <Mother 할아부지가맘에게넘겨주는이름={name} />;
}
function App() {
return <GrandFather />;
}
export default App;
입문강의인데, 밑도 끝도없이 다 구글링하라는 식이면
그냥 혼자 공부하지 뭐하러 강의듣지
// src/App.js
import React, { useState } from "react";
function Child(props) {
return (
<div>
<button
onClick={() => {
props.맘이아들에게넘겨준셋함수("박할아"); // 드디어 받은 setName을 실행합니다.
}}
>
할아버지 이름 바꾸기
</button>
<div>{props.맘이아들에게넘겨준할비이름}</div>
</div>
);
}
function Mother(props) {
return (
<Child
맘이아들에게넘겨준할비이름={props.할비가맘에게넘겨주는이름}
맘이아들에게넘겨준셋함수={props.할비가맘에게넘겨준셋함수}
/> // 받아서 다시 주고
);
}
function GrandFather() {
const [name, setName] = useState("김할아");
return (
<Mother
할비가맘에게넘겨주는이름={name}
할비가맘에게넘겨준셋함수={setName}
/>
); // 주고
}
function App() {
return <GrandFather/>;
}
export default App;
// src/App.js
import React, { useState } from "react";
function App() {
const onClickHandler = () => {
setName("누렁이가 됐지롱");
};
const [name, setName] = useState("길동이");
return (
<div>
{name}
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
>>
// src/App.js
import React, { useState } from "react";
function App() {
const [value, setValue] = useState("");
const onChangeHandler = (event) => {
const inputValue = event.target.value;
setValue(inputValue);
};
console.log("value:", value);
return (
<div>
<input type="text" value={value} onChange={onChangeHandler} />
</div>
);
}
export default App;
>> 불변성
메모리에 있는 값을 변경할 수 없는 것 = 불변성
자바스크립트 데이터형 : 원시데이터 / 원시데이터가 아닌 객체,배열,함수
let number = 1;
let number2 = 1;
이렇게 하면 number1,number2는 같은 데이터를 바라본다.
객체나 배열함수 등은 불변성이 없다.
리엑트에서 불변성에 주의해야 하는 이유??
→ 리액트는 state가 변했으면 ‘리랜터링'을 하고, state가 변하지 않았으면 ‘리랜더링’을 하지 않는다.
state가 변했는지 확인하는 방법 : state 변화 전과 후의 메모리 주소를 비교하는 것이다.
>> 컴포넌트와 렌더링
리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여 ui를 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미한다.
랜더링을 일으키는 것 -> 트리거링
렌더링 -> 요리하는 것
커밋 -> 실제로 손님테이블에 놓는 것
import React, { useState } from "react";
function App() {
const [number, setNumber] = useState(0);
return (
<div>
{number}
{/* 익명함수 */}
<button
onClick={() => {
setNumber(number + 1);
}}
>
{" "}
+{" "}
</button>
<button
onClick={() => {
setNumber(number - 1);
}}
>
-{" "}
</button>
</div>
);
}
export default App;
.app-style {
padding: 100px;
/* display:flex : flex박스 모델에 따라 자식들을 정렬해라는 설정 */
display: flex;
/* flex로 정렬된 요소들에 12px만큼의 간격을 부여하겠다라는 뜻 */
gap: 12px;
}
.square-style {
width: 100px;
height: 100px;
border: 1px solid green;
border-radius: 10px;
/* flex 박스 속성에는 alignItem과 justifyContent속성이 있음 */
display: flex;
/* alignItems : 열의 위치를 설정하는 속성 */
align-items: center;
/* justifyContent : 행의 위치를 설정하는 속성 */
justify-content: center;
}
import React from "react";
import "./App.css";
const App = () => {
return (
<div className="app-style">
<div className="square-style">감자</div>
<div className="square-style">고구마</div>
<div className="square-style">호박</div>
<div className="square-style">단호박</div>
<div className="square-style">알밤</div>
</div>
);
};
export default App;
Map을 사용하여 div 출력하기
import React from "react";
import "./App.css";
const App = () => {
// 맵을 사용하기 위해서 채소들 이름을 배열로 만들기
const vegetables = ["감자","고구마","호박","단호박","알밤"]
return (
<div className="app-style">
{/* 배열 vegetables에 map을 적용할건데 */}
{vegetables.map((vegetableName) =>{
return(
<div className="square-style" key={vegetableName}>
{vegetableName}
</div>
)
})}
</div>
);
};
export default App;
import React from "react";
import "./App.css"; // 🔥 반드시 App.css 파일을 import 해줘야 합니다.
function User(props) {
return (
<div className="square-style">
{props.user에넘긴값.age}살 - {props.user에넘긴값.name}
</div>
);
}
const App = () => {
const users = [
{ id: 1, age: 30, name: "송중기" },
{ id: 2, age: 24, name: "송강" },
{ id: 3, age: 21, name: "김유정" },
{ id: 4, age: 29, name: "구교환" },
];
return (
<div className="app-style">
{/* users의 정보들을 map이 돌면서, users 안의 정보들을 넘겨주고 있었고 */}
{users.map((a) => {
console.log("map이 뽑아온건 프로퍼티(옵젝이다) a : ", a);
console.log("a.id는 뭐야?", a.id);
return <User user에넘긴값={a} 여기도이름바꿔도되지={a.id}></User>;
})}
</div>
);
};
export default App;
14강 코드 내용
import React, { useState } from "react";
import "./App.css"; // 🔥 반드시 App.css 파일을 import 해줘야 합니다.
function CustomButton(props) {
const { color, onClick, children } = props;
if (color) {
return (
<button
style={{ backgroundColor: color, color: "white" }}
onClick={onClick}
>
{children}
</button>
);
}
return <button onClick={onClick}>{children}</button>;
}
function User(props) {
return (
<div className="square-style">
{props.user에넘긴값.age}살 - {props.user에넘긴값.name}
<CustomButton
color="red"
onClick={() => {
props.프롭스로넘길delete(props.user에넘긴값.id);
}}
>
삭제하기
</CustomButton>
</div>
);
}
const App = () => {
const [users, setUsers] = useState([
{ id: 1, age: 30, name: "송중기" },
{ id: 2, age: 24, name: "송강" },
{ id: 3, age: 21, name: "김유정" },
{ id: 4, age: 29, name: "구교환" },
]);
const [name, setName] = useState("");
const [age, setAge] = useState("");
const addUserHandler = () => {
console.log("함수 작동은 해?");
const newUser = {
id: users.length + 1,
age: age,
name: name,
};
console.log("newUser:", newUser);
// 기존배열을 먼저 이렇게 넣고, 새로운 user를 추가한 것
setUsers([...users, newUser]);
console.log("추가된 Users는?", users);
};
const deleteUserHandler = (id) => {
// user.id가 내가 설정한 id와 같지 않으면, 그것만 filter해서 새로운 유저리스트를 만들어라
const newUserList = users.filter((user) => user.id !== id);
setUsers(newUserList);
};
return (
<div>
<div className="app-style">
{/* users의 정보들을 map이 돌면서, users 안의 정보들을 넘겨주고 있었고 */}
{users.map((a) => {
console.log("map이 뽑아온건 프로퍼티(옵젝이다) a : ", a);
console.log("a.id는 뭐야?", a.id);
return (
<User
프롭스로넘길delete={deleteUserHandler}
user에넘긴값={a}
여기도이름바꿔도되지={a.id}
></User>
);
})}
</div>
<input
value={name}
placeholder="이름을 입력해주세요"
// 인풋 이벤트로 들어온 입력 값을 name의 값으로 업데이트
onChange={(e) => setName(e.target.value)}
/>
<input
value={age}
placeholder="나이를 입력해주세요"
// 인풋 이벤트로 들어온 입력 값을 age의 값으로 업데이트
onChange={(e) => setAge(e.target.value)}
/>
<CustomButton color="green" onClick={addUserHandler}>
추가하기
</CustomButton>
</div>
);
};
export default App;
'🌼 리액트 공부' 카테고리의 다른 글
리액트 네이티브 첫 수업 (실시간 강의) 정리 #1 (0) | 2022.12.29 |
---|---|
[리액트] Carousel (이미지 자동 슬라이드) 기능 구현하기 (0) | 2022.12.26 |
리액트 심화 강의 복습 / redux-toolkit , json-server, thunk , Axios (1) | 2022.12.23 |
[리액트] 리액트 심화 필기노트 (1) | 2022.12.08 |
[리액트] 리액트 입문강의 듣는중 / 리액트의 'state'란? (0) | 2022.12.04 |
댓글