리액트를 예습해보자.
/** * JSX란? JavaScript Extensions * 확장된 자바스크립트의 문법을 말한다 * * JSX 주의사항 * 1. 중괄호 내부에는 자바스크립트 표현식만 넣을 수 있다 * 2. 숫자, 문자열, 배열 값만 렌더링 된다 * 3. 모든 태그는 닫혀있어야 한다 * 4. 최상위 태그는 반드시 하나여야만 한다 */ const Main = () => { const number = 10; return ( <main> <h1>main</h1> <h2>{number % 2 === 0 ? "짝수" : "홀수"}</h2> </main> ); }; export default Main;
import "./Main.css"; //CSS파일 import const Main = () => { const user = { name: "안현희", isLogin: true, }; if (user.isLogin) { return <div className="logout">로그아웃</div>; //className (O), class (X) } else { return <div>로그인</div>; } }; export default Main;
JSX
는 HTML
과 JavaScript
를 동시에 사용하고 있기 때문에,//App.jsx import "./App.css"; import Header from "./components/Header"; import Main from "./components/Main"; import Footer from "./components/Footer"; import Button from "./components/Button"; function App() { //객체 형태로 만들어서 Props를 전달할 수 있다. const bottonProps = { text: "메일", color: "red", a: 1, b: 2, c: 3, }; return ( <> <Button {...bottonProps} /> <Button text={"카페"} /> <Button text={"블로그"}> <div>자식요소</div> //children <Header /> //children </Button> </> ); } export default App; //Botton.jsx const Button = ({ text, color, children }) => { return ( <button style={{ color: color }}> {text} - {color.toUpperCase()} {children} </button> ); }; //기본값 Button.defaultProps = { color: "black", }; export default Button;
Props
는 Properties
의 줄임말이라고 한다.const Button = ({ text, color, children }) => { /** * 이벤트객체 SyntheticBaseEvent * 브라우저 별 스펙이 달라서 생기는 문제를 해결해주는 합성이벤트 객체이다 * 일종의 통합 규격을 만드는것이다 */ const onClickButton = (e) => { console.log(e); //SyntheticBaseEvent console.log(text); }; return ( //onClickButton()이 아니라 onClickButton로 표기한다. <button onClick={onClickButton} style={{ color: color }}> {text} - {color.toUpperCase()} {children} </button> ); }; export default Button;
import "./App.css"; import { useState } from "react"; //useState는 react에서 기본으로 제공하는 내장함수이다 function App() { /** * useState라는 함수는 두 개 요소를 담은 배열을 반환한다 * 첫 번째 요소는 새롭게 생성된 state의 값이다 * 두 번째 요소는 state의 값을 변화시키는 함수이다 (상태변화함수라고 부른다.) * 따라서, 보통의 경우에 구조분해할당으로 값을 받는다 * 리액트 컴포넌트는 state값이 변환되었을때만 리렌더링 된다 */ const [count, setCount] = useState(0); const [light, setLight] = useState("OFF"); return ( <> <div> <h1>{light}</h1> <button onClick={() => { setLight(light === "ON" ? "OFF" : "ON"); }} {light === "ON" ? "끄기" : "켜기"} </button> </div> <div> <h1>{count}</h1> <button onClick={() => { setCount(count + 1); }} + </button> </div> </> ); } export default App;
//App.jsx import "./App.css"; import { useState } from "react"; import Bulb from "./components/Bulb"; import Counter from "./components/Counter"; function App() { return ( <> <Bulb /> <Counter /> </> ); } export default App; //Bulb.jsx import { useState } from "react"; const Bulb = () => { const [light, setLight] = useState("OFF"); return ( <div> {light === "ON" ? ( <h1 style={{ backgroundColor: "orange" }}>ON</h1> ) : ( <h1 style={{ backgroundColor: "gray" }}>OFF</h1> )} <button onClick={() => { setLight(light === "ON" ? "OFF" : "ON"); }} {light === "ON" ? "끄기" : "켜기"} </button> </div> ); }; export default Bulb; //Counter.jsx import { useState } from "react"; /** * * 리액트의 컴포넌트들은 세 가지 상황이 발생됐을때 리렌더링 되는데 * 1. state 값이 변경됐을때 * 2. props 값이 변경됐을때 * 3. 부모컴포넌트가 변경되면 자식 컴포넌트도 리렌더링된다 * 따라서, 불필요한 리렌더링을 막아주기 위해 다음과 같이 작성해본다 */ const Counter = () => { const [count, setCount] = useState(0); return ( <div> <h1>{count}</h1> <button onClick={() => { setCount(count + 1); }}> + </button> </div> ); }; export default Counter;
import { useState } from "react"; /** * useRef : 컴포넌트 내부의 변수로 활용가능 * 어떠한 경우에도 리렌더링을 하지 않음 * 렌더링에 영향을 미치고 싶지 않은 변수를 만들고 싶을때 사용한다 */ import { useRef } from "react"; /** * 간단한 회원가입 폼 만들어보기 * 1. 이름 * 2. 생년원일 * 3. 국적 * 4. 자기소개 */ const Register = () => { const [input, setInput] = useState({ name: "", birth: "", country: "", bio: "", }); const countRef = useRef(0); const inputRef = useRef(); const onChange = (e) => { countRef.current++; console.log(countRef.current); setInput({ ...input, [e.target.name]: e.target.value, }); }; const onSubmit = () => { if (input.name === "") { inputRef.current.focus(); } }; return ( <div> <div> <input ref={inputRef} //ref 속성으로 넣어준다. name="name" value={input.name} onChange={onChange} placeholder={"이름"} /> </div> <div> <input name="birth" value={input.birth} type="date" onChange={onChange} /> </div> <div> <select name="country" value={input.country} onChange={onChange}> <option value={""}></option> <option value={"kr"}>한국</option> <option value={"us"}>미국</option> <option value={"uk"}>영국</option> </select> </div> <div> <textarea name="bio" value={input.bio} onChange={onChange} /> </div> <button onClick={onSubmit}>제출</button> </div> ); }; export default Register;
ref
를 사용할때 컴포넌트 내, 외부로 변수를 선언해서 하면 안된다.
React Hooks
에는 이름앞에use
라는 접두사가 붙는다.React Hooks
는 함수 컴포넌트 내부에서만 호출될 수 있고,
조건문, 반복문 내부에서는 호출이 불가하다.- 또
use
라는 접두사를 활용하여 나만의Hook
을 만드는것도 가능하다.
import useInput from "../hooks/useInput"; /** * Hook관련 3가지 Tip * 1. 함수 컴포넌트, 커스텀 훅 내부에서만 호출 가능 * 2. 조건부로 호출 될 수 없다 * 3. 나만의 훅을 직접 만들 수 있다 */ const HookExam = () => { const [input, onChange] = useInput(); const [input2, onChange2] = useInput(); return ( <div> <input value={input} onChange={onChange} /> <input value={input2} onChange={onChange2} /> </div> ); }; export default HookExam; //---------------------------------------------------- //custom hooks(useInput.jsx) import { useState } from "react"; function useInput() { const [input, setInput] = useState(""); const onChange = (e) => { setInput(e.target.value); }; } export default useInput;