초급자를 위해 준비한
[웹 개발, 프론트엔드] 강의입니다.
리액트를 가장 쉽고 빠르게 배울 수 있는 리액트 입문 강의입니다. 토이 프로젝트를 만들면서 개념과 실전 감각을 익히고 배포까지 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)
댓글 남기기