React를 사용하기 위해 불러야 할 스크립트
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
React JS가 element를 생성하고 event listener를 더하는 것을 도와준다.
ReactDOM은 React element들을 가져다가 HTML로 바꿔준다.
JSX(JavaScript XML)는 리액트와 같은 라이브러리에서 사용하는 문법입니다.
자바스크립트 내부에서 HTML과 유사한 구문을 사용하여 UI구조를 작성하는데 사용됩니다.
<JSX>
과거문법
function WelcomeMessage() {
return React.createElement('h1', null, 'Hello, world!');
}
현재문법
function WelcomeMessage() {
return <h1>Hello, world!</h1>;
}
그런데 JSX문법으로 그냥 작성하면 html에서는 알아듣지 못한다. 대신 Babel을 가져와서 사용한다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
//ReactJS
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
//ReactDOM
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
//Babel
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel"> //꼭 넣어줘야 정상작동
const root = document.getElementById("root");
const Title = (
<h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
Hello~
</h3>
);
const Button = (
<button
style={{
backgroundColor: "tomato",
}}
onClick={() => console.log("im clicked")}
>
Click me!
</button>
);
const contatiner = React.createElement("div", null, [Title, Button]);
ReactDOM.render(contatiner, root);
</script>
</html>
더 나은 형태로 변형하면 다음과 같다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
function Title() {
return (
<h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
Hello~
</h3>
);
}
const Button = () => (
<button
style={{
backgroundColor: "tomato",
}}
onClick={() => console.log("im clicked")}
>
Click me!
</button>
);
const Container = () => (
<div>
<Title /> <Button />
</div>
);
ReactDOM.render(<Container />, root);
</script>
</html>
<State>
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
function App() {
let [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
return (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={onClick}>Click me!</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
state를 세팅하는 데는 2가지 방법이 있다.
1) 직접 할당 :setState(state +1)
2 )함수 할당:setState(state => state +1) (함수의 첫번째 인자는 현재 state 이다)
현재 state랑 관련이 없는 값을 새로운 state로 하고싶은 경우에는 (1),
현재 state에 조금의 변화를 주어서 새로운 state를 주고 싶은 경우에는 (2)
최종적으로는 2번 함수할당이 더 안전하다.
const [amount, setAmount] = React.useState(0);
const [inverted, setInverted] = React.useState(false);
두번째로 들어가는 함수는 실행될때마다 화면이 새로 렌더링된다는 것이 중요!
시간과 분 단위 변환하는 코드
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
function MinutesToHours() {
const [amount, setAmount] = React.useState(0);
const [inverted, setInverted] = React.useState(false);
const onChange = (event) => {
setAmount(event.target.value);
};
const reset = () => setAmount(0);
const onInvert = () => {
reset();
setInverted((current) => !current);
};
return (
<div>
<div>
<label htmlFor="minutes">Minutes</label>
<input
value={inverted ? amount * 60 : amount}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
disabled={inverted}
/>
</div>
<div>
<label htmlFor="hours">Hours</label>
<input
value={inverted ? amount : Math.round(amount / 60)}
id="hours"
placeholder="Hours"
type="number"
onChange={onChange}
disabled={!inverted}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onInvert}>
{inverted ? "Turn back" : "Invert"}
</button>
</div>
);
}
function KmToMiles() {
const [distance, setDistance] = React.useState(0);
const [flipped, setFlipped] = React.useState(false);
const onChange = (event) => {
setDistance(event.target.value);
};
const reset = () => setDistance(0);
const onFlip = () => {
reset();
setFlipped((current) => !current);
};
return (
<div>
<div>
<label htmlFor="km">KM</label>
<input
value={flipped ? Math.round(distance * 1.609344) : distance}
id="km"
placeholder="KM"
type="number"
onChange={onChange}
disabled={flipped}
/>
</div>
<div>
<label htmlFor="miles">Miles</label>
<input
value={flipped ? distance : Math.round(distance * 0.621371)}
id="miles"
placeholder="Miles"
type="number"
onChange={onChange}
disabled={!flipped}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onFlip}>{flipped ? "Turn back" : "Flip"}</button>
</div>
);
}
function App() {
const [index, setIndex] = React.useState("XX");
const onSelect = (event) => {
setIndex(event.target.value);
};
return (
<div>
<h1>Super Converter</h1>
<select value={index} onChange={onSelect}>
<option value="XX">Select your units</option>
<option value="0">Minutes & Hours</option>
<option value="1">Km & Miles</option>
</select>
<hr />
{index === "XX" ? "Please select your units" : null}
{index === "0" ? <MinutesToHours /> : null}
{index === "1" ? <KmToMiles /> : null}
{/* 2개일 때는 이거도 가능?
{index === "0" ? <MinutesToHours /> : <KmToMiles />}*/}
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
</script>
</html>
<Props>
Props(속성)은 React에서 데이터를 부모 컴포넌트로부터 자식 컴포넌트로 전달하는 방법입니다.
이렇게 props를 통해 컴포넌트 간에 데이터를 주고받을 수 있습니다.
Props는 읽기 전용이며, 자식 컴포넌트에서 변경할 수 없습니다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- PropTypes -->
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.min.js"></script>
<script type="text/babel">
function Btn({ text, fontSize = 12 }) {
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
padding: "10px 20px",
border: 0,
borderRadius: 10,
fontSize,
}}
>
{text}
</button>
);
}
Btn.propTypes = {
text: PropTypes.string.isRequired,
fontSize: PropTypes.number,
};
function App() {
return (
<div>
<Btn text="Save Changes" fontSize={18} />
<Btn text={"Continue"} />
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
</script>
</html>
<Create React App>
새로운 폴더를 만들고 싶은 공간에서
우클릭 -> 터미널 열기 실행후 다음과 같은 명령어를 입력하자.
npx create-react-app my-app(폴더명)
그러면 중간에 질문이 나오고 y를 누르면 된다.
해당 명령어를 통해 새로 생성하는 이유는 다음과 같다.
<EFFECTS>
• 리액트를 사용하는 이유: 최소 단위의 렌더링을 위해
• useState(): 변수, 변수를 제어하는 함수로 구성되며 변하는 값을 제어, 해당 부분의 리렌더링을 위함
• props: 태그의 속성 값을 함수의 아규먼트 처럼 컴포넌트에 값을 전달해준다.
• useEffect(): 코드의 실행 시점을 관리할 수 있는 선택권을 얻는 방어막 같은 존재, 디펜던시가 없을 경우 최초 1회 실행, 있을 경우 해당 값이 변할 경우 실행한다. 이 때 디펜던시는 여러개 입력이 가능하다.
🏴 부모 컴포넌트에서 리렌더링이 일어날 경우 모든 자식들이 리렌더링이 된다.(wa can use memo)
🏴 propType을 설치하고 props의 타입을 지정해 줄 수 있다. 이 때 isRequired로 필수값을 지정 가능
useEffect()란?
useEffect는 state의 상태를 감지 변경이 있을 때란 해당 컴포넌트를 랜더링한다.
useState(function(), []) [] 로 3가지 경우의 수 존재 ex) a, b 스테이트
1. 빈 배열을 넣는 경우, 최초 1회 랜더링 될 때만 실행한다.
2. [a] 하나의 state만 넣는 경우 a가 변경될 경우만 랜더링한다.
3. [a, b] a나 b중 하나가 값이 변경 될 때 랜더링한다.
useEffect 왜 써?
렌더링이 계속 된다면, 특히 특정 api를 불러오게 되는 경우 계속해서 불러오는 문제가 생길 수 있다.
state를 변경할 때, 계속해서 렌더링 되는 문제점이 존재한다. 많은 state가 존재한다면 성능 저하 문제가 발생할 수 있다. 이런 문제를 해결하기 위해 사용한다.
import { useEffect, useState } from "react";
function App() {
const [counter, setValue] = useState(0);
const [keyword, setKeyword] = useState("");
const onClick = () => setValue((prev) => prev + 1);
const onChange = (event) => setKeyword(event.target.value);
console.log("난 항상 실행중!");
useEffect(() => {
console.log("1번만 실행");
}, []);
useEffect(() => {
if (keyword !== "" && keyword.length > 5) {
console.log("키워드 변화에만 실행");
}
}, [keyword]);
useEffect(() => {
console.log("카운터 변화 실행");
}, [counter]);
return (
<div>
<input
value={keyword}
onChange={onChange}
type="text"
placeholder="Search here..."
></input>
<h1>{counter}</h1>
<button onClick={onClick}>Click me!</button>
</div>
);
}
export default App;
<To Do List>
import { useEffect, useState } from "react";
function App() {
const [toDo, setToDo] = useState("");
const [toDos, setToDos] = useState([]);
const onChange = (event) => setToDo(event.target.value);
const onSubmit = (event) => {
event.preventDefault();
if (toDo === "") {
return;
}
//중요한 로직
setToDos((currentArray) => [toDo, ...currentArray]);
setToDo("");
};
return (
<div>
<h1>My To Dos({toDos.length})</h1>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="write your to do..."
/>
<button>Add To Do</button>
</form>
</div>
);
}
export default App;
import { useEffect, useState } from "react";
function App() {
const [toDo, setToDo] = useState("");
const [toDos, setToDos] = useState([]);
const onChange = (event) => setToDo(event.target.value);
const onSubmit = (event) => {
event.preventDefault();
if (toDo === "") {
return;
}
setToDos((currentArray) => [toDo, ...currentArray]);
setToDo("");
};
return (
<div>
<h1>My To Dos({toDos.length})</h1>
<form onSubmit={onSubmit}>
<input
onChange={onChange}
value={toDo}
type="text"
placeholder="write your to do..."
/>
<button>Add To Do</button>
</form>
<hr />
<ul>
{toDos.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
export default App;
<Coin Tracker>
import { useEffect, useState } from "react";
function App() {
const [loading, setLoading] = useState(true);
const [coins, setCoins] = useState([]);
useEffect(() => {
fetch("https://api.coinpaprika.com/v1/tickers")
.then((response) => response.json())
.then((json) => {
setCoins(json);
setLoading(false);
});
}, []);
return (
<div>
<h1>The COIN TRADE {coins.length}</h1>
{loading ? <strong>Loading...</strong> : null}
<ul>
{coins.map((coin) => (
<li>
{coin.name} ({coin.symbol}): {coin.quotes.USD.price}
</li>
))}
</ul>
</div>
);
}
export default App;
<Movie App>
import { useState } from "react";
import Movie from "../components/Movie";
function Home() {
const [loading, setLoding] = useState(true);
const [movies, setMovies] = useState([]);
const getMovies = async () => {
const json = await (
await fetch(
`https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`
)
).json();
setMovies(json.data.movies);
setLoding(false);
};
useEffect(() => {
getMovies();
}, []);
console.log(movies);
return (
<div>
{loading ? (
<h1>Loading...</h1>
) : (
<div>
{movies.map((movie) => (
<Movie
key={movie.id}
medium_cover_image={movie.medium_cover_image}
title={movie.title}
summary={movie.summary}
genres={movie.genres}
/>
))}
</div>
)}
</div>
);
}
export default Home;
npm i react-router-dom@5.3.0
'입사후 공부한 내용' 카테고리의 다른 글
[C#] 기본 개념 (0) | 2023.06.23 |
---|---|
[개념정리] 오버로딩, 오버라이딩 (0) | 2023.06.22 |
[MSSQL] 연결 에러 해결! (0) | 2023.06.16 |
[ASP.NET] MVC강의 기초 및 심화 (0) | 2023.06.13 |
[ASP.NET] 개념과 역사 (0) | 2023.06.13 |