TAB 2022 2학기 학회활동 [팀 스터디]
TIL 포스팅입니다.
작성자 : 40기_강한림
노마드 코더 - ReactJS로 영화 웹 서비스 만들기 수강 과정입니다.
5.0부터 진행하는 코딩중, 웹 사이트를 열고싶을때는, vscode의 터미널에서 'npm start'을 입력합니다. //폴더 찾아가서 index.html 열었는데 아무것도 안나와서 당황하지 않도록.. // 무언가 터미널에 뜨면 y 나 n을 누르면 잘 뜹니다.
3.6
- 지난 3챕터(3.0~3.5)의 복습 강의 입니다.
추가된 코드가 있어 작성합니다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script
crossorigin
src="https://unpkg.com/react@17/umd/react.production.min.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@17/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 [minutes, setMinutes] = React.useState(0);
const onChange = (event) => {
setMinutes(event.target.value);
};
const reset = () => setMinutes(0);
return (
<div>
<h1 className="hi">Super Converter</h1>
<label htmlfor="minutes">Minutes</label>
<div>
<input
value={minutes}
id="minutes"
placeholder="Minutes"
type="number"
onChange={onChange}
/>
</div>
<div>
<label htmlfor="hours">Hours</label>
<input
value={Math.round(minutes / 60)}
id="hours"
placeholder="Hours"
type="number"
disabled
/>
</div>
<button onClick={reset}>Reset</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</html>
- const onChange 아래에 reset 함수를 추가했습니다.
- minutes와 같이 hours 또한 div로 묶고, minutes을 60으로 나눈뒤 반올림(round)하여 화면에 표기되도록 하였습니다
- hours의 input 속성에 'disabled' 속성을 추가했습니다.
3.7
학습 목표 : 단위 변환을 뒤집는 함수(flip function)을 만드는 것 입니다.
- 클릭하면, hours는 입력가능하게 하고, minutes을 입력 불가능 하게 합니다. 다시 누르면, 반대로 만듭니다.
함수 'onFlip'을 작성합니다. 그리고, 이 함수에서 새로운 state를 조작하도록 합니다.
새로운 state를 만듭니다.
const [flipped, setflipped] = React.useState(false);
default 값은 false 입니다.
onFilp 값을 가지고 있는 버튼을 누르면, flipped 값을 반전시키도록 합니다.
const onFlip = () => setFilpped((current) => !current);
disabled의 값은 명시적으로(true, false)로 쓸 수 있습니다.
다음과 같이 수정합니다.
disabled={flipped === false}
flipped의 값이 false이면, hours는 disabled 상태가 됩니다. 반대로, true이면, minutes가 disabled 상태가 됩니다.
minutes의 input 속성에 다음을 추가합니다.
disabled={flipped === true}
더 짧게 작성하면,
disabled={flipped}
disabled={!flipped}
// 위는 minutes의 속성, 아래는 hours의 속성 입니다
hours에 입력이 되도록 할 것입니다. // onChange 속성을 input에 추가합니다.
주의할 점은, 'value={Math round minutes / 60}'은 작성이 minutes에 되었을때 작동되어야 한다는 것 입니다.
flipped 값에 따라서, 해당 속성이 실행되지 않게 할 수 있습니다.
value={flipped ? minutes : Math.round(minutes / 60)}
flipped값이 true라면, state에 있는 값(minutes)를 그대로 보여줍니다.
minutes의 값을 amount로 변경합니다. setMinutes도 setAmount로 변경합니다. 기존에 작성된 코드들도 수정합니다.
const [amount, setAmount] = React.useState(0);
조건문 방식을 minutes 측에도 추가해줍니다.
value={flipped ? amount * 60 : amount}
onFlip 함수에 setFlipped 말고도, reset함수도 실행되도록 합니다.
const onFlip = () => {
reset();
setFilpped((current) => !current);
};
3.8
지난 강의의 복습입니다.
진행중 const[flipped, setFlipped]과, flip 버튼에서 변경점이 있습니다.
const [inverted, setInverted] = React.useState(false);
//버튼 변경점
<button onClick={onInvert}>
{inverted ? "Turn back" : "Invert"}
</button>
3.9
학습 목표 : 메뉴바를 만들어서 사용자가 원하는 단위변환기를 선택할 수 있도록 합니다.
마일/킬로미터 변환기를 추가로 만듭니다.
APP 컴포넌트를 복사+붙여넣기해서 새로운 컴포넌트(마일/킬로미터 변환기)로 사용합니다.
컴포넌트는 그 안에 또 다른 컴포넌트를 렌더링 할 수 있습니다. // 자신안에 다른 컴포넌트를 불러올 수 있다.
그 부분 까지 추가하여 작성하면 다음과 같습니다.
function App() {
return (
<div>
<h1 className="hi">Super Converter</h1>
<MinutesToHours />
</div>
);
}
이 컴포넌트는 분/시간 변환기와 마일/킬로미터 변환기를 담는 컴포넌트가 될 것입니다. (APP 컴포넌트)
마일/킬로미터 변환기를 위한 새로운 컴포넌트를 만듭니다.
- 완성은 본인이 하게 됩니다(강의 내용중 알려주지 않음)
select 함수를 만들어서 어떤 컴포넌트의 내용을 보여줄지 선택하도록 합니다.
const [index, setIndex] = React.useState("0");
select 태그를 사용해서(html에 있는 태그입니다.) 작성합니다. select는 option들을 가집니다.
option들에 value(속성)을 줍니다.
<select>
<option value="0">Minutes & Hours</option>
<option value="1">Km & Miles</option>
</select>
변화를 읽도록 합니다. select에 onChange속성을 줍니다.
그리고 onSelect event listener (event 반환)을 만듭니다
const onSelect = (event) => {
setIndex(event.target.value);
};
어떤 컴포넌트를 보여줄지 선택하는 기능을 만듭니다.
{}내에는 JS를 작성할 수 있습니다.
{index === "0" ? <MinutesToHours /> : null}
{index === "1" ? <KmToMiles /> : null}
index의 초기 값을 xx로 바꾸고, xx를 value로 갖는 option을 추가합니다.
이것을 시작화면으로 할 수 있습니다.
state를 변경하면, 모든것이 새로고침 됩니다. (return 부분이 다시 실행됩니다.)
4.0
props는 일종의 방식으로, 부모 컴포넌트(APP)에서 자식 컴포넌트(MinutesToHours)로 데이터를 보낼 수 있도록 해주는 방법입니다.
학습목표 : 부모 컴포넌트에서 자식 컴포넌트로 데이터를 보내는 예시 만들기
- props가 왜 필요한지 알아봅니다.
버튼 태그에 style 속성을 추가해 스타일을 변경할 수 있습니다.
중괄호{{ }}를 2개 중첩하여 작성해야함을 주의합니다.
function saveBtn() {
return <button style={{}}>SAVE</button>;
}
만약 btn이 여러개 존재하고, 이것들의 style이 모두 동일한데, 이름만 다르다면 어떻게 해야 할까요?
모든 style을 재사용 하고 싶고, 하지만 텍스트를 설정하거나 변경하고 싶을때는요?
새로운 정보를 Btn 컴포넌트에 전송해봅시다. // savebtn을 Btn으로 수정합니다.
속성(구문 syntax)는 특정 태그에 정보를 전송할 수 있습니다.
<Btn text="Save">
Btn의 text의 값(value)를 save로 주어도 btn에는 text 속성이 없기 때문에(전달해 줄 수 없기 때문에)
아무것도 변하지 않습니다.
만들고, 사용할 수 있는 컴포넌트들은 ()로 인자(argument)를 받을 수 있습니다.
이 인자가 곧 props 입니다.
다음 코드는 모두 동일합니다.
Btn({banana:"save"})
//아래 코드와 동일함
<Btn banana="save"/>
왜냐하면, Btn은 함수이기 때문입니다.
어떤 prop이던, Btn 컴포넌트로 보내면, 그것은 Btn 함수의 첫번째 인자로 들어가게 됩니다.
props는 컴포넌트(함수)가 전달받는 첫번째 인자이면서 유일한 인자입니다.
그리고 동시에 props는 우리가 다른 컴포넌트(함수)에서 보낸 정보들을 갖는 오브젝트(object) 입니다.
다음과 같이 작성한다면, props는 banana:"save"와 y:7이 됩니다.
consol.log 시, {banana: "save", y: 7}이라고 뜹니다.
<Btn banana: "save" y={7}/>
현재 object(props)는 banana와 y라는 key를 가지고있습니다.//이후 y는 삭제합니다.
function Btn(props){
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
border:0,
}}
>
{props.banana}
</button>
);
}
이 경우 btn에는 banana속성의 문자열이 표시되게 될 것입니다.
props는 오브젝트이기 때문에, {}를 사용할 수 있습니다.
그래서, 다음과 같이 작성할 수 있습니다.
function Btn({banana}){
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
border:0,
}}
>
{banana}
</button>
);
}
props는 오브젝트 이기에, banana가 안에 들어갈 수 있습니다.
1개 이상의 key를 가질 수 있습니다.
function Btn({banana, big}){
return (
<button
style={{
backgroundColor: "tomato",
color: "white",
border:0,
fontSize : big ? 18: 16 // big가 true이면, 18pt, false이면, 16pt로 설정
}}
>
{banana}
</button>
);
}
4.1 //조금 어려운 내용
학습목표 : props에 무엇을 넣을 수 있는지 알아봅니다.
4.0에서, bool과 string을 넣을 수 있는것을 확인했습니다.
function도 보낼 수 있습니다.
Btn들에 onClick function을 주고자 합니다.
onClick function은 App 컴포넌트에 있는 것들의 state를 바꾸게 될 것입니다.
Btn의 text를 state연결합니다.
const [value, setValue] = React.useState("Save Changes") // state의 기본값 : Save Changes
const changeValue = () => setValue("Revert Changes");
changeValue 함수를 Btn의 onClick으로 보냅니다.
이것은 Btn으로 들어가는 prop입니다. // eventlistener가 아님에 주의합니다. prop의 이름일 뿐입니다.
컴포넌트 App 내부에 추가한 <Btn>에는 style을 지정할 수 없습니다.
prop을 가져와서 적용시켜야 합니다.
function Btn의 인자(props)에 text와 마찬가지로, onClick을 추가해줍니다.
function Btn({text, onClick}){
return (
<button
onClick={onClick} // 좌변의 onClick(eventlistener), 우변의 onClick(prop)
style={{
backgroundColor: "tomato",
color: "white",
border:0,
fontSize : big ? 18: 16 // big가 true이면, 18pt, false이면, 16pt로 설정
}}
>
{text}
</button>
);
}
onClick이 중복되어서, prop의 이름을 changeValue로 바꿉니다.
function Btn({text, changeValue}){
return (
<button
onClick={changeValue}
style={{
backgroundColor: "tomato",
color: "white",
border:0,
fontSize : big ? 18: 16 // big가 true이면, 18pt, false이면, 16pt로 설정
}}
>
{text}
</button>
);
}
어떤것이던 prop으로 넣는다면, 자동으로 return으로 들어가지 않습니다.
원하는곳에 직접 집어넣어야 합니다.
컴포넌트가 상태 변경을 겪으면, return에 있는 모든 것은 re-render 됩니다.
만약 return에 자식 컴포넌트가 있다면, 그것 또한 re-render 됩니다.
하지만, re-render 될 필요가 없거나, 되지 말아야 한다면 다음과 같은 방법을 사용해야 합니다.
- react MEMO
prop이 변경되지 않는 한에서, 우리는 컴포넌트 등이 re-render될지 말지를 결정 할 수 있습니다.
<Btn text = {value} onClick = {changeValue} />
<Btn text = "Continue" />
첫번째 Btn의 props는 state와 연결되어있기 때문에, re-render되어야 합니다.
state가 변경된다면 props도 변경되기 때문에 re-render되어야 합니다.
하지만, 두번째 Btn의 props는 변경되지 않습니다.
react MEMO 사용방법
(Btn 컴포넌트와, App컴포넌트 사이에 넣습니다(어느 function에도 들어가지 않음))
const MemorisedBtn = React.memo()
두개의 Btn을 MemorisedBtn으로 수정합니다.
<MemorisedBtn text = {value} onClick = {changeValue} />
<MemorisedBtn text = "Continue" />
이후 첫번째 버튼을 눌러도, 두번째 버튼은 re-render되지 않습니다.
4.2
학습 목표 : props를 완료합니다.
- props types을 배웁니다.
사용자가 prop으로 fontSize를 전달하도록 합니다.
<Btn text = "Save Changes" fontSize={18} />
//function Btn({text, fontSize}) 로 수정
propType는 어떤 타입의 prop을 받고 있는지 체크해줍니다.
그 이전에 propType를 설치해줍니다.
<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
다음과 같이 작성해 text와 fontSize에는 어떤 자료형이 와야하는지 정의해 줄 수 있습니다.
Btn.propTypes = {
text: PropTypes.string,
fontSize: PropTypes.number,
};
확실하게 하고 싶다면 뒤에 ,'isRequired'를 붙여줍니다.
Btn.propTypes = {
text: PropTypes.string.isRequired,
fontSize: PropTypes.number,
};
prop에도 기본값을 지정해 줄 수 있습니다. //JS 때문에 가능합니다.
function Btn({text, fontSize = 16})
4.3
props의 복습입니다.
5.0
이후 수업을 위한 준비 과정입니다
nodejs를 설치합니다.
이후
window 검색창에서 cmd(명령 프롬프트)를 검색한뒤 실행합니다.
'node - v'와 'npx'가 실행되는지 확인합니다.
이후 문제가 좀 있었습니다..(해결은 했습니다)
분명 'npx create-react-app react-for-start(이부분은 이름)'을 입력했는데 E404가 잔뜩떠서... // creat 아니고 create...
검색해 봤더니 그냥 삭제하고 재설치하면.. 된다고 하길래 해봤더니 진짜로 됐습니다.
[React] npx create-react-app 가 실행되지 않을 때 (tistory.com) 이쪽을 참고했습니다.
이후 작성하는 모든 파일은 npm 으로 생성한 폴더 내에있는 src 폴더에 생성합니다.
index.js를 수정합니다.
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
이것만 남기고 다 지웁니다.
App.js에서도 지웁니다.
function App() {
return (
<div>
<h1>HELLO! :D</h1>
</div>
);
}
export default App;
내부에 div 태그 하나만 남기고 전부 지웁니다. //h1태그는 선택입니다.
이후 src 파일에서, App.js와 index.js를 제외하고 전부 삭제합니다.
5.1
과거에 수행한 동작들을 creat-react-app으로 다시 수행해 봅니다.
src 폴더에 Button.js 파일을 생성한 뒤, 시작합니다.
function으로 Button을 만들고, 이것은 text라는 이름의 props를 가집니다.
function Button({ text }) {
return <button>{text}</button>;
}
export default Button;
- App.js 에서 Button을 가져올 수 있도록, export default Button을 입력합니다.
import Button from "./Button";
- App.js에는 다음을 입력합니다.
컴포넌트를 불러오는법, props를 사용하는 법은 전과 동일합니다.
text를 prop으로 전달합니다.
현재의 App.js는 이러합니다.
import Button from "./Button";
function App() {
return (
<div>
<h1>HELLO! :D</h1>
<Button text={"Continue"} />
</div>
);
}
export default App;
터미널에 npm i prop-types를 입력합니다.
이후 import PropTypes from "prop-types";를 작성합니다.
import App from "./App";
import PropTypes from "prop-types";
function Button({ text }) {
return <button>{text}</button>;
}
Button.propTypes = {
text: PropTypes.string.isRequired,
};
export default App;
style.css 파일을 생성합니다.
다음과 같이 작성합니다.
button {
color: white;
background-color: tomato;
}
// 저는 이 상황에서 이러한 오류가 발생했습니다...
styles.css를 사용하면 페이지의 모든 버튼이 영향을 받게 됩니다.
그래서, css modules을 사용합니다.
styles.css의 이름을 Button.module.css로 변경합니다.
이 css는 Button.js에 import 합니다.
import App from "./App";
import PropTypes from "prop-types";
import styles from "./Button.module.css";
function Button({ text }) {
return <button className={styles.btn}>{text}</button>;
}
Button.propTypes = {
text: PropTypes.string.isRequired,
};
export default App;
//오류가 또 떴는데 또 새로운 오류다
어플리케이션을 위해 새로운 css module을 생성합니다.
btn과 마찬가지로, 작성해줍니다
위는 App.module.css이고,
아래는 App.js입니다.
.title {
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
import Button from "./Button";
import styles from "./App.module.css";
function App() {
return (
<div>
<h1 className={styles.title}>HELLO! :D</h1>
<Button text={"Continue"} />
</div>
);
}
export default App;
//코드가 잘못된건가 해서, 강의에서 제공된 코드를 그대로 복사- 붙여넣기했는데도, 오류가 뜨는군용...
6장
- 6장은 최종 요약만을 해서 작성합니다.
6.1
- 요약 :
'22 - 1학기 > 팀 스터디' 카테고리의 다른 글
[웹 FE 스터디] #7 PRACTICE MOVIE APP (0) | 2022.11.03 |
---|---|
[웹 FE 스터디] ReactJs ~6.4 (0) | 2022.11.03 |
[웹 FE 스터디] ReactJS ~ 3.5 (0) | 2022.10.06 |
[웹 FE 스터디] 리액트 시작하기(3) (0) | 2022.10.06 |
[웹 FE 스터디] REACT ~3.5 (0) | 2022.10.06 |