TAB 2022 2학기 학회활동 [팀 스터디]
TIL 포스팅입니다.
작성자 : 40기_박지민
노마드 코더 - ReactJS로 영화 웹 서비스 만들기
▶ 시간↔분 전환 프로그램 예제
<!DOCTYPE html>
<html lang="ko">
<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>HourMinute_converter</title>
</head>
<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 App(){
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>
<h1>Converterrrr</h1>
<label htmlFor="minutes">Minutes</label>
<input
value ={inverted?amount*60:amount}
type = "number"
placeholder ="Minutes"
id="minutes"
onChange ={onChange}
disabled={inverted}
/>
</div>
<div>
<label htmlFor="hours">Hours</label>
<input
value ={inverted?amount:Math.round(amount/60)}
type = "number"
placeholder ="Hours"
id="hours"
onChange ={onChange}
disabled={!inverted}
/>
</div>
<button onClick={reset}>Reset</button>
<button onClick={onInvert}>
{inverted?"Turn back":"Invert"}
</button>
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />,root);
</script>
</html>
- onChange의 기능
: input 태그의 이벤트를 감지. 값 변경 시 setAmount를 이용해 변경된 값을 state안에 삽입.
데이터 수정을 위해 modifier function (=setAmount) 이 사용되었기 때문에 그 함수를 사용할 때마다 컴포넌트는 새 데이터와 함께 새로고침 됨.
* onChange = { onChange } 가 없을 경우 우변의 onChange prop에 담긴 modifier function이 작동하지 않는다. 이벤트 발생 시 수정된 값으로 업데이트 시켜주는 기능이 사라졌기 때문에 input이 키보드이벤트를 감지해도 그 내부의 값은 디폴트값 0에서 업데이트가 이뤄지지 않는다.
- 삼항연산자
: 다른 프로그래밍 언어와 동일한 방식
(조건문? 참일 경우 실행시킬 내용 : 거짓일 경우 실행시킬 내용) 으로 표현한다.
컴포넌트 내에서 jsx 형태로 {}에 넣어 표현할 수 있다.
- Math.round()
: 반올림 함수. 소수 첫째자리에서 반올림시켜준다.
▶시간↔분 / 미터↔킬로미터 변환 프로그램 예제
<!DOCTYPE html>
<html lang="ko">
<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>HourMinute_converter</title>
</head>
<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(){...
function KmToMiles(){... // 앞 내용과 유사하여 생략
function App(){
const [index,setIndex] = React.useState("0")
const onSelect = (event) =>{
setIndex(event.target.value);
};
return(
<div>
<h1>Super Converter</h1>
<select value = {index} onChange={onSelect}>
<option value= "0">Minutes & Hours</option>
<option value ="1">Km & Miles</option>
</select>
{index ==="0"?<MinutesToHours />: null}
{index==="1"?<KmToMiles />:null}
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />,root);
</script>
</html>
- { index ==="0"?<MInutesToHours />: null }
: 만약 index의 값이 0이라면 MinutesToHours 컴포넌트를 렌더링하고, 아니라면 아무것도 보여주지 않는다는 뜻.
현 index의 디폴트값이 0이기 때문에 자동으로 MinutesToHours컴포넌트가 렌더링 된 상태.
그걸 원하지 않는다면 function App(){} 의 내용을 아래와 같이 변경할 수 있다
function App(){
const [index,setIndex] = React.useState("x")
const onSelect = (event) =>{
setIndex(event.target.value);
};
return(
<div>
<h1>Super Converter</h1>
<select value = {index} onChange={onSelect}>
<option value = "x">Select your units</>
<option value= "0">Minutes & Hours</option>
<option value ="1">Km & Miles</option>
</select>
{index ==="0"?<MinutesToHours />: null}
{index==="1"?<KmToMiles />:null}
</div>
);
}
index의 초기값을 x로 변경하고 그 경우의 옵션을 추가하였기 때문에 처음 실행 시 select창에는 "Select your units"문구가 뜨고 index의 값이 0도 1도 아니기 때문에 어떤 컴포넌트도 실행되지 않는다.
이 이후 선택지를 클릭하면 index의 value가 변경되며 리렌더링 되는데
이때 console.log("render w/", index);를 통해 그 변화를 확인할 수 있다.
▶Props
부모 컴포넌트로부터 자식 컴포넌트에 데이터를 보낼 수 있게 해주는 방법
function Btn({text,big}){
return <button style={{
backgroundColor:"tomato",
color:"black",
padding : "10px 20px",
border:0,
borderRadius:10,
fontSize:big?18:16,
}}>{text}</button>;
}
function App(){
return(
<div>
<Btn text = "Save Changes" big={true}/>
<Btn text = "Continue" big = {false}/>
</div>
);
}
- Btn() 괄호 내의 {text,big}이 Btn의 인자이자 Btn으로부터 전달받는 props.
- 첫 번째 함수형 컴포넌트에 의해 text자리에 " Save Changes"가 들어간 버튼이 생성된다. 부모 컴포넌트로부터 big의 값은 true라는 데이터가 Btn 컴포넌트에 보내졌기 때문에 ( fontSize : big? 18 : 16 ) 에 의해 폰트 크기는 18이 된다.
- <Btn style = {{color:"pink"}} text = {value} big = {true} /> 로 작성해도 style은 반영되지 않는다. 이곳에 작성한 style은 button이 아니라 Btn컴포넌트에 달린 style이기 때문에 Btn에서 prop를 가져와서 적용시켜야 한다.
▶React.memo( )
props가 변경되지 않으면 리렌더링 할 필요가 없도록 한다.
function Btn({text,onClick}){
console.log(text, "was rendered")
return (
<div>
<button
onClick={onClick}
style={{
backgroundColor:"tomato",
color:"black",
padding : "10px 20px",
border:0,
borderRadius:10,
fontSize:16,
}}>{text}</button></div>);
}
const MemorizedBtn = React.memo(Btn)
function App(){
const [value,setValue] = React.useState("Save Changes");
const changeValue = () => setValue ("Revert Changes");
return(
<div>
<MemorizedBtn text = {value} onClick = {changeValue} />
<MemorizedBtn text = "Continue" />
</div>
);
}
const root = document.getElementById("root");
ReactDOM.render(<App />,root);
- 첫 번째 버튼이 클릭될 때 onClick에 의해 value가 변경되지만 두 번째 버튼은 변경되는 것이 없다.
이 때 MemorizedBtn은 React.memo(Btn)이기 때문에 prop의 변경이 없는 두 번째 버튼은 리렌더링 되지 않는다.
* 콘솔에 Continue was rendered 문구가 뜰 일이 없음
▶PropTypes
props 타입 지정. 타입 오류 시 경고문구가 올라온다.
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
PropTypes 사용을 위해 위의 내용을 필요로 한다.
- 사용 방식
function 컴포넌트명({prop}){ return {prop};} 컴포넌트명.propTypes ={ prop(종류): PropTypes.자료형}; |
Ex) Btn.propTypes ={ text: PropTypes.string, fontSize : PropTypes.number,};
- .isRequired
: 타입 지정을 확실히 하고 싶을 때, 즉 특정한 컴포넌트가 특정 prop만을 가지고 렌더링된다는 것을 확실히 하고 싶을 때 사용.
특정 prop.PropTypes.자료형.isRequired 형태.
▶Create-react-app
Node.js의 설치를 필요로 한다.
Node.js
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
nodejs.org
다음 페이지에서 설치 후 터미널에서 node -v 와 npx 를 입력해 정상적으로 설치되었는지 확인한다.
npx create-react-app 프로젝트명 code 프로젝트명 |
으로 Vscode에서 프로젝트를 열 수 있다.
터미널에 npm start 를 입력해주면 개발용 서버가 자동으로 준비된다.
( *package.json : 모든 스크립트 존재 , src: 모든 파일들이 들어갈 폴더
* 컴포넌트 든 파일에 import 컴포넌트명 from "./컴포넌트명"
* App.js 메인 파일에 export default 컴포넌트명 추가해야 App.js에서 컴포넌트를 가져올 수 있다. )
▶Proptypes 사용
터미널에 npm i prop-types 입력해서 설치.
PropTypes사용될 파일에 import PropTypes from "prop-type" 추가
사용방식은
function 컴포넌트명({prop}){ return <tag>{prop}</tag>;}
컴포넌트명.propTypes ={ prop(종류): PropTypes.자료형.isRequired}; 으로
create-react-app으로 작업하지 않았을 때와 동일.
▶CSS
기존 css의 추가 방법
1. css파일 생성 후 index.js에 import "./파일명.css"; 추가
=> 해당 태그 가진 모든 파일이 css 내 내용을 갖게 된다 (global css style)
css파일이 적용하려는 파일의 모든 부분에 import된다
2. style prop 사용 style = {{ css 내용 }}
=> 직접적이라 번거롭다
∴ 컴포넌트명.module.css형태의 파일 생성.
해당 컴포넌트가 든 파일에 import styles from "./컴포넌트명.module.css" 추가
컴포넌트 내에서 css가 들어갈 태그에 className = {sytles.css클래스명} 추가
동일한 class이름과 컴포넌트를 다른 파일 내에서도 사용할 수 있다.
▶useEffect
state가 변화할 때 모든 컴포넌트는 다시 실행되고, 모든 코드들도 다시 실행.
이 때 무슨 일이 있어도 코드가 특정 상황에서만 실행되도록 하기 위해 useEffect 사용.
import {useState ,useEffect} from "react";
- > useEffect 사용할 파일에 들어가야 할 코드
const iRunOnlyOnce = () => { console.log("i run only once.")};
useEffect(iRunOnlyOnce, [] ); //[]: 빈 배열
useEffect 안 함수는 state의 변화에 관계없이 API를 한번만 호출하고 다시는 하지 않는다.
component가 처음 렌더링 될 때 실행되고 다시는 실행되지 않는다.
useEffect(()=>{
console.log("i run only once.");
},[]);
다음과 같이 함수명을 따로 지정하지 않고도 사용 가능하다.
useEffect = (()=>{
if (keyword!==""&& keyword.length<6){
console.log("Search For",keyword);
}
},[ keyword ]);
빈 배열 [ ] 내에 특정 state를 넣으면 그 값이 변경될 때만 실행되도록 할 수 있다. 두 개 이상의 state가 들어와도 됨.
'22 - 1학기 > 팀 스터디' 카테고리의 다른 글
[웹 FE 스터디] 리액트 토이프로젝트 | useState, useEffect, API, Router (0) | 2022.11.07 |
---|---|
[웹 FE 스터디] #7 PRACTICE MOVIE APP (0) | 2022.11.03 |
[웹 FE 스터디] 3.6~6.4 (0) | 2022.11.03 |
[웹 FE 스터디] ReactJS ~ 3.5 (0) | 2022.10.06 |
[웹 FE 스터디] 리액트 시작하기(3) (0) | 2022.10.06 |