초급자를 위해 준비한
[웹 개발, 프론트엔드] 강의입니다.
리액트를 가장 쉽고 빠르게 배울 수 있는 리액트 입문 강의입니다. 토이 프로젝트를 만들면서 개념과 실전 감각을 익히고 배포까지 3시간 만에 완성하는 알짜 강의! 초급, 중급, 고급으로 구성된 시리즈의 첫 번째 강의입니다 :)
✍️
이런 걸
배워요!
리액트 개발
프런트엔드 개발
웹 개발
나만의 토이프로젝트
백엔드 연동
강의 :
https://www.inflearn.com/course/만들면서-배우는-리액트-기초#
https://github.com/milooy/cat-jjal-maker/blob/main/answers/2-setup.html
https://github.com/braverokmc79/cat-short-app
https://github.com/braverokmc79/react-cat-short-app
[6].리액트 앱에 숨 불어넣기
27. 실제 고양이 데이터 받아오기 - fetch, Open API
강의:
<script>
const getCatData=async () =>{
return await fetch("https://cataas.com/cat?json=true")
.then((response) => response.json())
.then((data) => data);
}
async function geCats(){
const data =await getCatData();
console.log("data : " ,data);
}
geCats();
</script>
콘솔창 출력
- createdAt: "2022-05-01T21:03:13.331Z"
- file: "626ef5917f254a0017b56506.gif"
- mimetype: "image/gif"
- owner: "null"
- size: 1982059
- tags: (5) ['fall', 'snow', 'slow motion', 'ears', 'gif']
- updatedAt: "2022-10-11T07:52:32.684Z"
- url: "/cat/vjQhaUpsIcSMOthc"
- validated: true
- _id: "vjQhaUpsIcSMOthc"
- [[Prototype]]: Object
28.고양이 데이터 내 앱에 연동하기
강의 :
//Form 폼 시작
const Form=({updateMainCat })=>{
const [value, setValue] =React.useState("");
const includesHangul = (text) => /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/i.test(text);
const [errorMessage , setErrorMessage] =React.useState("");
function handleInputChange(e){
const useValue=e.target.value;
setErrorMessage("");
if(includesHangul(useValue)){
setErrorMessage("한글은 입력할 수 없습니다.");
}
setValue(e.target.value.toUpperCase()) ;
}
function handleFormSubmit(e){
e.preventDefault();
setErrorMessage("");
if(value===''){
setErrorMessage("빈값으로 만들 수 없습니다.");
return;
}
//업데이트 하기
updateMainCat(value);
}
return (
<form onSubmit={handleFormSubmit}>
<input type="text" name="name" placeholder="영어 대사를 입력해주세요"
value={value}
onChange={handleInputChange}
/>
<button type="submit">생성</button>
<p style={{color:"red"}}>{errorMessage}</p>
</form>
);
}
//Form 폼 끝
const fetchCat = async (text) => {
const OPEN_API_DOMAIN = "https://cataas.com";
const response = await fetch(`${OPEN_API_DOMAIN}/cat/says/${text}?json=true`);
const responseJson = await response.json();
return `${OPEN_API_DOMAIN}/${responseJson.url}`;
};
async function updateMainCat(value){
const nextCounter =counter+1;
setCounter(nextCounter);
jsonLocalStorage.setItem("counter",nextCounter);
const nIndex= Math.floor(Math.random()* mainImageSrcArr.length);
//setMainCardImgSrc(mainImageSrcArr[nIndex]);
const img = await fetchCat(value);
setMainCardImgSrc(img);
}
29. 컴포넌트 생성시 고양이 데이터 받아오기 - useEffect
강의 :
~
const [mainCardImgSrc, setMainCardImgSrc] =React.useState("");
async function setInitialCat(){
const newCat=await fetchCat("First cat ");
console.log(newCat);
setMainCardImgSrc(newCat);
}
React.useEffect(()=>{
setInitialCat();
}, []);
~
30. useEffect 의 정체
강의 :
31. 조건부 렌더링
강의 :
const MainCard=({alreadyFavorite, mainCardImgSrc, onHeartClick ,alt,width })=>{
const EMPTY_HEART = "????";
const FULL_HEART = "????";
const heartIcon =alreadyFavorite ? FULL_HEART: EMPTY_HEART;
return (
<div className="main-card">
<img
src={mainCardImgSrc}
alt={alt}
width={width}
/>
<button onClick={onHeartClick} >{heartIcon}</button>
</div>
);
}
const App=()=>{
const CAT1 = "https://cataas.com/cat/HSENVDU4ZMqy7KQ0/says/react";
const CAT2 = "https://cataas.com/cat/BxqL2EjFmtxDkAm2/says/inflearn";
const CAT3 = "https://cataas.com/cat/18MD6byVC1yKGpXp/says/JavaScript";
const cats= [CAT1,CAT2];
const [favorites , setFavorites]=React.useState(jsonLocalStorage.getItem("favorites") || []);
const [counter ,setCounter ] =React.useState(jsonLocalStorage.getItem("counter"));
const [mainCardImgSrc, setMainCardImgSrc] =React.useState("");
const alreadyFavorite = favorites.includes(mainCardImgSrc);
async function setInitialCat(){
const newCat=await fetchCat("First cat ");
console.log(newCat);
setMainCardImgSrc(newCat);
}
React.useEffect(()=>{
setInitialCat();
}, []);
~
return(
<div>
<Title>{counter}번째 고양이 가라사대</Title>,
<Form updateMainCat={updateMainCat} />
<MainCard alreadyFavorite={alreadyFavorite} mainCardImgSrc={mainCardImgSrc} onHeartClick={onHeartClick} alt="alt" width="400" />
<Favorites favorites={favorites} />
</div>
)
32.퀴즈풀이
강의 :
const counterTitle =counter===null ? "" : counter +"번째 ";
return(
<div>
<Title>{counterTitle} 고양이 가라사대</Title>,
33. setState 더 알아보기-함수, 지연초기화
강의 :
const [favorites , setFavorites]=React.useState(()=>{
return jsonLocalStorage.getItem("favorites") || [];
});
const [counter ,setCounter ] =React.useState(()=>{
return jsonLocalStorage.getItem("counter")
});
async function updateMainCat(value){
//const nIndex= Math.floor(Math.random()* mainImageSrcArr.length);
//setMainCardImgSrc(mainImageSrcArr[nIndex]);
const img = await fetchCat(value);
setMainCardImgSrc(img);
setCounter((prev)=>{
const nextCounter =prev+1;
jsonLocalStorage.setItem("counter",nextCounter);
return nextCounter;
});
}
[7].실무 개발환경 만들기
34. create-react-app-실무 개발환경 만들기
강의 :
npx create-react-app cat-jjal-maker-cra
35. create-react-app 폴더 구조 뜯어보기2
강의 :
36. 지금까지 만든 앱 create-react-app 으로 옮기기
강의 :
App.css
body {
text-align: center;
}
.main-card button {
position: relative;
left: -45px;
bottom: 15px;
}
.favorites {
list-style: none;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
}
.favorites img {
width: 150px;
}
form{
margin-bottom: 20px;
}
App.js
import logo from "./logo.svg";
import "./App.css";
import { useEffect, useState } from "react";
import { Title } from "./components/Title";
import Form from "./components/Form";
import MainCard from "./components/MainCard";
import Favorites from "./components/Favorites";
const App = () => {
const [loading, setLoading] = useState(false);
const jsonLocalStorage = {
setItem: (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
},
getItem: (key) => {
return JSON.parse(localStorage.getItem(key));
},
};
const fetchCat = async (text) => {
const OPEN_API_DOMAIN = "https://cataas.com";
const response = await fetch(
`${OPEN_API_DOMAIN}/cat/says/${text}?json=true`
);
const responseJson = await response.json();
return `${OPEN_API_DOMAIN}/${responseJson.url}`;
};
const [favorites, setFavorites] = useState(() => {
return jsonLocalStorage.getItem("favorites") || [];
});
const [counter, setCounter] = useState(() => {
return jsonLocalStorage.getItem("counter");
});
const [mainCardImgSrc, setMainCardImgSrc] = useState("");
const alreadyFavorite = favorites.includes(mainCardImgSrc);
async function setInitialCat() {
const newCat = await fetchCat("First cat ");
console.log(newCat);
setMainCardImgSrc(newCat);
}
useEffect(() => {
setInitialCat();
}, []);
function onHeartClick() {
const nextFavorites = [...favorites, mainCardImgSrc];
setFavorites(nextFavorites);
jsonLocalStorage.setItem("favorites", nextFavorites);
}
async function updateMainCat(value) {
setLoading(true);
const img = await fetchCat(value);
setMainCardImgSrc(img);
setCounter((prev) => {
const nextCounter = prev + 1;
jsonLocalStorage.setItem("counter", nextCounter);
setTimeout(() => {
setLoading(false);
}, 500);
return nextCounter;
});
}
const counterTitle = counter === null ? "" : counter + "번째 ";
return (
<div>
<Title>{counterTitle} 고양이 가라사대</Title>,
<Form updateMainCat={updateMainCat} loading={loading} />
<MainCard
alreadyFavorite={alreadyFavorite}
mainCardImgSrc={mainCardImgSrc}
onHeartClick={onHeartClick}
alt="alt"
width="400"
/>
<Favorites favorites={favorites} />
</div>
);
};
export default App;
components/CatItem.js
import React from "react";
export const CatItem = (props) => {
return (
<>
<li>
<img src={props.img} style={{ width: "150px" }} alt="props.img" />
</li>
</>
);
};
components/Favorites.js
import React from "react";
import { CatItem } from "./CatItem";
const Favorites = ({ favorites }) => {
if (favorites.length === 0) {
return <div>사진 위 하트를 눌러 고양이 사진을 저장해봐요!</div>;
}
return (
<ul className="favorites">
{favorites.map((cat, index) => (
<CatItem img={cat} key={index} />
))}
</ul>
);
};
export default Favorites;
components/Form.js
import React, { useState } from "react";
const Form = ({ updateMainCat, loading }) => {
const [value, setValue] = useState("");
const includesHangul = (text) => /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/i.test(text);
const [errorMessage, setErrorMessage] = React.useState("");
function handleInputChange(e) {
const useValue = e.target.value;
setErrorMessage("");
if (includesHangul(useValue)) {
setErrorMessage("한글은 입력할 수 없습니다.");
}
setValue(e.target.value.toUpperCase());
}
function handleFormSubmit(e) {
e.preventDefault();
setErrorMessage("");
if (value === "") {
setErrorMessage("빈값으로 만들 수 없습니다.");
return;
}
//업데이트 하기
updateMainCat(value);
}
return (
<form onSubmit={handleFormSubmit}>
<input
type="text"
name="name"
placeholder="영어 대사를 입력해주세요"
value={value}
onChange={handleInputChange}
/>
{loading ? (
<button type="button">로딩중</button>
) : (
<button type="submit">생성</button>
)}
<p style={{ color: "red" }}>{errorMessage}</p>
</form>
);
};
export default Form;
components/MainCard.js
import React from "react";
const MainCard = ({
alreadyFavorite,
mainCardImgSrc,
onHeartClick,
alt,
width,
}) => {
const EMPTY_HEART = "????";
const FULL_HEART = "????";
const heartIcon = alreadyFavorite ? FULL_HEART : EMPTY_HEART;
return (
<div className="main-card">
<img src={mainCardImgSrc} alt={alt} width={width} />
<button onClick={onHeartClick}>{heartIcon}</button>
</div>
);
};
export default MainCard;
components/Title.js
import React from "react";
export const Title = (props) => {
return <h1>{props.children}</h1>;
};
37.빌드한 결과물 github pages로 배포하기
강의 :













댓글 ( 4)
댓글 남기기