소플의 처음 만난 리액트 -초청 강의 수강
Hook
-훅은 무조건 최상위레벨에서만 호출해야 한다.
-컴포넌트가 렌더링될 때마다 매번 같은 순서로 호출되어야 한다.
-리액트 함수 컴포넌트에서만(+우리가 직접만든 커스텀내에서도) 훅을 호출해야 한다.
-훅이 많아지면 헷갈리기에 상단에 훅을 호출하는 것을 모아 놓아 구분하는 것이 좋음
플러그인 추천
eslint-plugin-react-hooks
의존성배열이 잘못되면 알려줌
Custom Hook 만들기
-이름이 use로 시작하고 내부에서 다른 훅을 호출하는 하나의 자바스크립트 함수
-재사용성을 높이기 위한 목적으로 사용
▼ 아래와 같이 두가지 예시가 중복되는 코드가 많을 때 사용한다.
▼ 위 코드에서 커스텀 훅을 만든 코드
Custom Hook 사용하기
▼ 위 코드에서 훅을 사용한 코드
*useCounter() 커스텀 훅 예제
chapter_07
import React,{useEffect,useState} from "react";
import useCounter from "./useCounter";
const MAX_CAPACITY=10;
function Accommodate(props){
const [isFull,setIsFull]=useState(false);
const [count, increaseCount,decreaseCount]=useCounter(0);
useEffect(()=>{
console.log('===============');
console.log('useEffect() is called.');
console.log(`isFull:${isFull}`);
})
useEffect(()=>{
setIsFull(count>= MAX_CAPACITY);
console.log(`Current count value: ${count}`);
},[count]);
return(
<div style={{padding:16}}>
<div style={{ padding: 16 }}>
<p>{`총 ${count}명 수용했습니다.`}</p>
<button onClick={increaseCount} disabled={isFull}>
입장
</button>
<button onClick={decreaseCount}>퇴장</button>
{isFull && <p style={{ color: "red" }}>정원이 가득찼습니다.</p>}
</div>
</div>
)
}
export default Accommodate;
import {useState} from 'react';
function useCounter(initialValue){
const [count,setCount]=useState(initialValue);
const increaseCount=()=>setCount((count)=>count+1);//안전하려면 그냥 count+1말고 앞에 (count)=>count+1이렇게 앞에 붙여주는게 좋음
const decreaseCount=()=>setCount((count)=>Math.max(count-1,0));
return [count,increaseCount,decreaseCount];
}
export default useCounter;
React Event
이벤트 리스너(event listener)
이벤트 리스너란 이벤트가 발생했을 때 그 처리를 담당하는 함수를 가리키며, 이벤트 핸들러(event handler)라고도 한다.
onclick, textinput많이 사용
파라미터
* 클릭이벤트 처리하기 예제 -교재 p.261
import React, { useState } from "react";
function ConfirmButton(props) {
const [isConfirmed, setIsConfirmed] = useState(false);
const handleConfirm = () => {
setIsConfirmed((prevIsConfirmed) => !prevIsConfirmed);
};
return (
<button onClick={handleConfirm} disabled={isConfirmed}>
{isConfirmed ? "확인됨" : "확인하기"}
</button>
);
}
export default ConfirmButton;
condition rendering
조건에 따른 렌더링
condition=조건
자바스크립트의 Truthy와 falsy
엘리먼트 변수 Element Variables
리액트 엘리먼트를 변수처럼 다루는 방법
렌더링해야할 컴포넌트를 변수처럼 다루고 싶을 때 사용
인라인 조건 inline condition
조건문을 코드 안에 집어 넣는 것
많이 사용
inline If-Else
?연산자를 사용 (삼항연산자)
condition?true:false
많이 사용
작성참고
로그인 여부를 나타내는 툴바 -교재 p.279
inline-if, inline else
chapter_09
Toolbar.jsx
import React from "react";
const styles = {
wrapper: {
padding: 16,
display: "flex",
flexDirection: "row",
borderBottom: "1px solid grey",
},
greeting: {
marginRight: 8,
},
};
function Toolbar(props) {
const { isLoggedIn, onClickLogin, onClickLogout } = props;
return (
<div style={styles.wrapper}>
{isLoggedIn && <span style={styles.greeting}>환영합니다!</span>}
{isLoggedIn ? (
<button onClick={onClickLogout}>로그아웃</button>
) : (
<button onClick={onClickLogin}>로그인</button>
)}
</div>
);
}
export default Toolbar;
LandingPage.jsx
import React, { useState } from "react";
import Toolbar from "./Toolbar";
function LandingPage(props) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const onClickLogin = () => {
setIsLoggedIn(true);
};
const onClickLogout = () => {
setIsLoggedIn(false);
};
return (
<div>
<Toolbar
isLoggedIn={isLoggedIn}
onClickLogin={onClickLogin}
onClickLogout={onClickLogout}
/>
<div style={{ padding: 16 }}>소플과 함께하는 리액트 공부!</div>
</div>
);
}
export default LandingPage;
▼디버깅할때 잠깐 랜더링 막아 놓을 때 이렇게 사용하면 좋음(일단 보여주는거 막으라 할때 임시적으로 가려놓고 나중에다시 보여서 배포하라하면 지우면 됨)
▼ 실행화면
출석부 출력하기 예제 -교재 p.299
chapter_10
AttendanceBook.jsx
import React from "react";
const students = [
{
id: 1,
name: "Inje",
},
{
id: 2,
name: "Steve",
},
{
id: 3,
name: "Bill",
},
{
id: 4,
name: "Jeff",
},
];
function AttendanceBook(props) {
return (
<ul>
{students.map((student, index) => {
return <li key={student.id}>{student.name}</li>;
})}
{/* {students.map((student, index) => {
return <li key={`student.id-${student.id}`}>{student.name}</li>;
})} */}
</ul>
);
}
export default AttendanceBook;
사용자 정보 입력받기 예제 -교재 p.324
chapter_11
SignUp.jsx
import React, { useState } from "react";
function SignUp(props) {
const [name, setName] = useState("");
const [gender, setGender] = useState("남자");
const handleChangeName = (event) => {
setName(event.target.value);
};
const handleChangeGender = (event) => {
setGender(event.target.value);
};
const handleSubmit = (event) => {
alert(`이름: ${name}, 성별: ${gender}`);
event.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
<label>
이름:
<input type="text" value={name} onChange={handleChangeName} />
</label>
<br />
<label>
성별:
<select value={gender} onChange={handleChangeGender}>
<option value="남자">남자</option>
<option value="여자">여자</option>
</select>
</label>
<button type="submit">제출</button>
</form>
);
}
export default SignUp;
섭씨 온도와 화씨온도 표시하기 예제- p.346
chapter_12
Calculator.jsx
import React, { useState } from "react";
import TemperatureInput from "./TemperatureInput";
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>물이 끓습니다.</p>;
}
return <p>물이 끓지 않습니다.</p>;
}
function toCelsius(fahrenheit) {
return ((fahrenheit - 32) * 5) / 9;
}
function toFahrenheit(celsius) {
return (celsius * 9) / 5 + 32;
}
function tryConvert(temperature, convert) {
const input = parseFloat(temperature);
if (Number.isNaN(input)) {
return "";
}
const output = convert(input);
const rounded = Math.round(output * 1000) / 1000;
return rounded.toString();
}
function Calculator(props) {
const [temperature, setTemperature] = useState("");
const [scale, setScale] = useState("c");
const handleCelsiusChange = (temperature) => {
setTemperature(temperature);
setScale("c");
};
const handleFahrenheitChange = (temperature) => {
setTemperature(temperature);
setScale("f");
};
const celsius =
scale === "f" ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit =
scale === "c" ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={handleCelsiusChange}
/>
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={handleFahrenheitChange}
/>
<BoilingVerdict celsius={parseFloat(celsius)} />
</div>
);
}
export default Calculator;
TemperatureInput.jsx
const scaleNames = {
c: "섭씨",
f: "화씨",
};
function TemperatureInput(props) {
const handleChange = (event) => {
props.onTemperatureChange(event.target.value);
};
return (
<fieldset>
<legend>
온도를 입력해주세요(단위:{scaleNames[props.scale]}):
</legend>
<input value={props.temperature} onChange={handleChange} />
</fieldset>
);
}
export default TemperatureInput;
Card컴포넌트 만들기 예제 -p.369
chapter_13
Card.jsx
function Card(props) {
const { title, backgroundColor, children } = props;
return (
<div
style={{
margin: 8,
padding: 8,
borderRadius: 8,
boxShadow: "0px 0px 4px grey",
backgroundColor: backgroundColor || "white",
}}
>
{title && <h1>{title}</h1>}
{children}
</div>
);
}
export default Card;
ProfileCard.jsx
import Card from "./Card";
function ProfileCard(props) {
return (
<Card title="Nana" backgroundColor="#4ea04e">
<p>안녕하세요, 나나입니다.</p>
<p>저는 리액트를 사용해서 개발하고 있습니다.</p>
</Card>
);
}
export default ProfileCard;
컨텍스트 사용해 테마변경 기능만들기 예제 -p.397
chpater_14
DarkOrLight.jsx
import { useState, useCallback } from "react";
import ThemeContext from "./ThemeContext";
import MainContent from "./MainContent";
function DarkOrLight(props) {
const [theme, setTheme] = useState("light");
const toggleTheme = useCallback(() => {
if (theme == "light") {
setTheme("dark");
} else if (theme == "dark") {
setTheme("light");
}
}, [theme]);
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<MainContent />
</ThemeContext.Provider>
);
}
export default DarkOrLight;
MainContent.jsx
import { useContext } from "react";
import ThemeContext from "./ThemeContext";
function MainContent(props) {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div
style={{
width: "100vw",
height: "100vh",
padding: "1.5rem",
backgroundColor: theme == "light" ? "white" : "black",
color: theme == "light" ? "black" : "white",
}}
>
<p>안녕하세요, 테마 변경이 가능한 웹사이트 입니다.</p>
<button onClick={toggleTheme}>테마 변경</button>
</div>
);
}
export default MainContent;
ThemeContext.jsx
import React from "react";
const ThemeContext = React.createContext();
ThemeContext.displayName = "ThemeContext";
export default ThemeContext;
스타일컴포넌트 사용해 스타일링 예제 -p.436
chapter_15
Blocks.jsx
import styled from "styled-components";
const Wrapper = styled.div`
padding: 1rem;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: flex-start;
background-color: lightgrey;
`;
const Block = styled.div`
padding: ${(props) => props.padding};
border: 1px solid black;
border-radius: 1rem;
background-color: ${(props) => props.backgroundColor};
color: white;
font-size: 2rem;
font-weight: bold;
text-align: center;
`;
const blockItems = [
{
label: "1",
padding: "1rem",
backgroundColor: "red",
},
{
label: "2",
padding: "3rem",
backgroundColor: "green",
},
{
label: "3",
padding: "2rem",
backgroundColor: "blue",
},
];
function Blocks(props) {
return (
<Wrapper>
{blockItems.map((blockItem) => {
return (
<Block
padding={blockItem.padding}
backgroundColor={blockItem.backgroundColor}
>
{blockItem.label}
</Block>
);
})}
</Wrapper>
);
}
export default Blocks;
'React > 소플 React 강의' 카테고리의 다른 글
[2022.07.30]소플 강의 정리 3 (0) | 2022.07.30 |
---|---|
[2022.07.28]React- 소플 강의 정리 (0) | 2022.07.28 |