ReactJS로 영화 웹 서비스 만들기
노마드 코더 강의 (ReactJS로 영화 웹 서비스 만들기)
👋 React, JSX 처음 접하기
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><div id="root"></div></body><script src="https://unpkg.com/react@18/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@18/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');const Title = () => (<h3>Hi, it's title</h3>);// const h3 = React.createElement(// 'h3',// null,// "Hi, it's title"// );const Button = () => (<buttononClick={() => console.log('clicked!')}onMouseEnter={() => console.log('entered!')}>click me!</button>);// const btn = React.createElement(// 'button',// {// onClick: () => console.log('clicked!'),// onMouseEnter: () => console.log('entered!')// },// 'click me!'// );const Container = () => (<div><Title /><Button /></div>);// const container = React.createElement(// 'div',// null,// [Title, Button]// );ReactDOM.render(<Container />, root);</script></html>
🫐 State
[참고] React와 바닐라 자바스크립트 동작의 차이
배열 안 요소들의 변수명을 지정해주는 문법 (JS)
const arr = [1, 2, 3];const [a, b, c] = arr;console.log(a); // 1console.log(b); // 2console.log(c); // 3
React.useState()
console.log(React.useState(0));
const [state, setState] = React.useState(초기값);
setState(1); // 이렇게하면 state 값이 1이 된다.
const [state, setState] = React.useState(초기값);const onClick = () => {setState(state+1);};return (<div><h3>Total clicks: {state}</h3><button onClick={onClick}></button></div>);
State 실습-1 (클릭하면 숫자가 올라가는 Counter)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><div id="root"></div></body><script src="https://unpkg.com/react@18/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@18/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() {const [counter, setCounter] = React.useState(0);const onClick = () => {// setCounter(counter + 1);setCounter((current) => current + 1); // 위쪽 각주처리된 코드보다 이처럼 현재값으로 지정해주는 것이 더 안전하다.};return (<div><h3>Total clicks: {counter}</h3><button onClick={onClick}>Click me!</button></div>);}ReactDOM.render(<App />, root);</script></html>

JSX와 HTML
<h1 className="hi">Super Converter</h1><label htmlFor="minutes">Minutes</label><input id="minutes" placeholder="Minutes" type="number" /><label htmlFor="hours">Hours</label><input id="hours" placeholder="hours" type="number" />
State 실습-2 (Hours-Minutes Converter)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><div id="root"></div></body><script src="https://unpkg.com/react@18/umd/react.production.min.js"></script><script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script><script src="https://unpkg.com/@babel/standalone/babel.min.js"></script><script type="text/babel">function App() {const [amount, setAmount] = React.useState(""); // State 초기값을 빈 값으로 설정const [inverted, setInverted] = React.useState(false); // State 초기값을 false로 설정const onChange = (event) => { // input 태그에 change가 발생하면 실행setAmount(event.target.value); // input 태그의 value로 amount 설정};const reset = () => { // Reset버튼 누르면 실행setAmount("");};const onInvert = () => { // Insert Hours(Minutes)버튼 누르면 실행reset(); // 우선 값을 비워준다.setInverted((current) => !current); // 이 또한 현재값 이용, Boolean을 반대로 전환};return (<div><h1 className="hi">Super Converter</h1><div><label htmlFor="minutes">Minutes</label><inputvalue={inverted ? amount * 60 : amount} // 삼항연산자 사용id="minutes"placeholder="Minutes"type="number"onChange={onChange}disabled={inverted} // inverted가 true일때 disabled/></div><div><label htmlFor="hours">Hours</label><inputvalue={inverted ? amount : amount / 60}id="hours"placeholder="hours"type="number"onChange={onChange}disabled={!inverted} // inverted가 false일때 disabled/></div><button onClick={reset}>Reset</button><button onClick={onInvert}>{inverted ? "Insert Minutes" : "Insert Hours"}</button>// inverted가 true인지 false인지에 따라 버튼의 content가 변경됨</div>);}const root = document.getElementById("root");ReactDOM.render(<App />, root);</script></html>

Divide-and-Conquer (State 마무리)
<script>function MinutesToHours() { // <MinutesToHours /> (컴포넌트)const [amount, setAmount] = React.useState("");const [inverted, setInverted] = React.useState(false);const onChange = (event) => {setAmount(event.target.value);};const reset = () => {setAmount("");};const onInvert = () => {reset();setInverted((current) => !current);};return (<div><h3 className="hi">Minutes To Hours Converter</h3><div><label htmlFor="Minutes">Minutes</label><inputvalue={inverted ? amount * 60 : amount}id="Minutes"placeholder="Minutes"type="number"onChange={onChange}disabled={inverted}/></div><div><label htmlFor="Hours">Hours</label><inputvalue={inverted ? amount : (amount / 60).toFixed(2)}id="Hours"placeholder="Hours"type="number"onChange={onChange}disabled={!inverted}/></div><button onClick={reset}>Reset</button><button onClick={onInvert}>{inverted ? "Insert Minutes" : "Insert Hours"}</button></div>);}function KmToMiles() { // <KmToMiles /> (컴포넌트)const [amount, setAmount] = React.useState("");const [inverted, setInverted] = React.useState(false);const onChange = (event) => {setAmount(event.target.value);};const reset = () => {setAmount("");};const onInvert = () => {reset();setInverted((current) => !current);};return (<div><h3 className="hi">Km To Hours Converter</h3><div><label htmlFor="Km">Km</label><inputvalue={inverted ? (amount * 1.609).toFixed(2) : amount}id="Km"placeholder="Km"type="number"onChange={onChange}disabled={inverted}/></div><div><label htmlFor="Miles">Miles</label><inputvalue={inverted ? amount : (amount / 1.609).toFixed(2)}id="Miles"placeholder="Miles"type="number"onChange={onChange}disabled={!inverted}/></div><button onClick={reset}>Reset</button><button onClick={onInvert}>{inverted ? "Insert Km" : "Insert Miles"}</button></div>);}function App() { // 두가지 컴포넌트를 select의 value에 따라 삼항연산자를 통해 랜더링const [index, setIndex] = React.useState("0");const onChange = (event) => {setIndex(event.target.value);};return (<div><h1 className="hi">Super Converter</h1><select onChange={onChange}><option value="0">Minutes To Hours</option><option value="1">Km To Miles</option></select><hr />{index === "0" ? <MinutesToHours /> : null}{index === "1" ? <KmToMiles /> : null}</div>);}const root = document.getElementById("root");ReactDOM.render(<App />, root);</script>
🍒 Props
function Btn(props) {return (<buttonstyle={{backgroundColor: "tomato",border: "none",padding: 10,margin: 10,}}>{props.text}</button>);}function App() {return (<div><Btn text="Confirm" /><Btn text="Submit" /></div>);}const root = document.getElementById("root");ReactDOM.render(<App />, root);
function Btn({text, 아무거나}) {return (<buttonstyle={{backgroundColor: "tomato",border: "none",padding: 10,margin: 10,}}>{text}{아무거나}</button>);}function App() {return (<div><Btn text="Confirm" 아무거나="ㅎㅇ"/><Btn text="Submit" 아무거나="ㅎㅇ"/></div>);}
onClick에 전달하기 React.memo
function Btn({text, changeValue}) {return (<buttononClick={changeValue}style={{backgroundColor: "tomato",border: "none",padding: 10,margin: 10,}}>{text}</button>);}function App() {const [value, setValue] = React.useState("Save Changes");const changeValue = () => setValue("Revert Changes");return (<div><Btn text={value} changeValue={changeValue} /><Btn text="Submit" /></div>);}
React.memo()
function Btn({text, changeValue}) {return (<buttononClick={changeValue}style={{backgroundColor: "tomato",border: "none",padding: 10,margin: 10,}}>{text}</button>);}const MemorizedBtn = React.memo(Btn);function App() {const [value, setValue] = React.useState("Save Changes");const changeValue = () => setValue("Revert Changes");return (<div><MemorizedBtn text={value} changeValue={changeValue} /><MemorizedBtn text="Submit" /></div>);}
propTypes
Btn.propTypes = {text: PropTypes.string.isRequired, // text값 필수, 문자형fontSize: PropTypes.number, // 숫자형};
🔥 Create-React-App
리액트 앱 생성하기
npx craete-react-app (생성할 앱 이름)cd (생성한 앱 이름)npm start
CSS 적용해보기
.title {font-family: 'Courier New', Courier, monospace;font-size: 18px;}
import Button from './Button';import styles from './App.module.css';function App() {return (<div><h1 className={styles.title}>Welcome back!</h1><Button text={'Continue'} /></div>);}export default App;
💥 Effect
import { useState, useEffect } from 'react';function App() {const [counter, setValue] = useState(0);const onClick = () => setValue((prev) => prev + 1);console.log('I run all the time');const iRunOnlyOnce = () => {console.log('I Run Only Once');}useEffect(iRunOnlyOnce, []);return (<div><h1>{counter}</h1><button onClick={onClick}>Click Me!</button></div>);}export default App;
import { useState, useEffect } from 'react';function App() {const [counter, setValue] = useState(0);const [keyword, setKeyword] = useState('');const onClick = () => setValue((prev) => prev + 1);const onChange = (e) => setKeyword(e.target.value);useEffect(() => {console.log(`Keyword Changes! ${keyword}`);}, [keyword]);useEffect(() => {console.log(`Counter Changes! ${counter}`);}, [counter]);useEffect(() => {console.log(`Keyword or Counter Changes!`);}, [keyword, counter]);return (<div><input type='text' onChange={onChange} /><h1>{counter}</h1><button onClick={onClick}>Click Me!</button></div>);}export default App;
import { useState, useEffect } from 'react';function App() {function Hello() {useEffect(() => {console.log('Hi :)');return () => {console.log('Bye :(');};}, []);return <h1>Hello!</h1>;}const [showing, setShowing] = useState(false);const onClick = () => {setShowing((prev) => !prev);};return (<div><button onClick={onClick}>{showing ? 'Hide' : 'Show'}</button>{showing ? <Hello /> : null}</div>);}export default App;
📜 To-do List 만들기
import { useState } from 'react';function App() {const [todo, setTodo] = useState('');const [todos, setTodos] = useState([]);const onChange = (e) => setTodo(e.target.value);const onSubmit = (e) => {e.preventDefault();if (todo === '') {return;}setTodos((currentArr) => [...currentArr, todo]);setTodo('');};const onClick = (index) => {setTodos((currentArr) => {currentArr.splice(index, 1);return [...currentArr];});};return (<div><h1>My TODOS! ({todos.length})</h1><form onSubmit={onSubmit}><inputonChange={onChange}value={todo}type='text'placeholder='Write To Do!'></input><button>Add To Do</button></form><hr /><ul>{todos.map((item, index) => {return (<li key={index}>{item}<button onClick={() => onClick(index)}>X</button></li>);})}</ul></div>);}export default App;