상세 컨텐츠

본문 제목

React(리액트) 티키타카 14 (useEffect Hook + fetch )

React

by e7e 2024. 10. 13. 16:34

본문

2024.10.09 - [React] - React(리액트) 티키타카 13 (useEffect Hook )

까지도 벌써 읽었다면, 당신은 정말 대단하당. React와 오해없이 기꺼이 친구가 될꺼이당.

 

이번시간엔 useEffect를 어케 쓰는지 쪼메 더 써보장.(헉 마치 수업인듯... 왠지 하품 남...)

프론트 프레임워크들은 기본적으로  CSR(Client Side Rendering)기반 

SPA(Single Page Application)를 법의 허락없이 감히 강요한다 하였당.

SPA를 구현하려면 AJAX 사용은  어쩔 수 없당. (금수저는 하루만에 AJAX다린이 되었당!)

 

AJAX를 써보려니  당근빠따 Restful 서버의 필요가 또 어쩔 수 없당.

누군가는 여기서 Spring Boot를 기대할 수도 있당. (미안하당 아직 아니당~~😝)

 

json-server 모듈을 이용한다면, 금방 연습용을 만들수 있으닝, 맹글어보장

 

REACTSTUDY 폴더 아래에 myjsonserver라고 폴더를 맹글장.

Terminal(cmd)에서  아래 명령어를 오타없이 잘치장.

cd myjsonserver
npm init -y 

 

package.json 파일이 생기면  고 안에 아래 내용을 추가하장.(import  사용을 위해서. 기억남??)

" type":"module",

 

아래 임시로 쓸 json형식 더미 데이터  파일을 myjsonserver 폴더에 맹글장.(복사/붙여넣깅)

db.json

{
  "friends": [
    { "id": "f01", "name": "경민", "age": 24, "avatar": "Leo",      "job": "기획" },
    { "id": "f02", "name": "미누", "age": 42, "avatar": "Luis",     "job": "개발" },
    { "id": "f03", "name": "병철", "age": 28, "avatar": "Sarah",    "job": "오류" },
    { "id": "f04", "name": "미영", "age": 30, "avatar": "Vivian",   "job": "운영"},
    { "id": "f05", "name": "선주", "age": 29, "avatar": "Maria",    "job": "감독"},
    { "id": "f06", "name": "나흠", "age": 34, "avatar": "Jocelyn",  "job": "관리"},
    { "id": "f07", "name": "원영", "age": 21, "avatar": "Riley",    "job": "노래"},
    { "id": "f08", "name": "선경", "age": 26, "avatar": "Brooklynn","job": "놀기"},
    { "id": "f09", "name": "리나", "age": 23, "avatar": "Sawyer",   "job": "댄스"},
    { "id": "f10", "name": "미선", "age": 26, "avatar": "Katherine","job": "런런"},
    { "id": "f11", "name": "선영", "age": 23, "avatar": "Eden",     "job": "그림" },
    { "id": "f12", "name": "오호", "age": 37, "avatar": "Brian",    "job": "설계" }
  ]
}

 

이제 Terminal(cmd)에 아래 명령어를 입력하여 보장.

npx json-server db.json --port 8272

아래와 같지 않다면 당신 손가락의 오류당.(참고로 여긴 오류동이당!!)

브라우져 주소 표시줄에  아래 값들을 넣어서 결과를 확인해서 느끼미를 얻장.

http://localhost:8272/

http://localhost:8272/friends

http://localhost:8272/friends/f05

 

만약 구글에서 "Chorme 웹 스토어" 로 검색 후  웹스토어에서 아래 처럼 "JSON Beautifier..." 검색후

해당 플러그인을 Chrome 확장프로그램에 추가한다면... 

JSON 형식 데이터를 아래 처럼 다양한 형식으로 예쁘게 볼수 있겠당.

난 이미 지난 글에서 화면 캡쳐에 지치고 말았당.

 

혹  브라우져에 나온 결과가 당신의 호기심을 자극했다면, "db.json 파일을  랜덤데이터를 

이용해서 자동으로 만들수 있다면 아주 유용하겠는 걸"  머 그런 저런 생각을 했다면

2024.05.02 - [NodeJS] - Restful용 가짜 data 서비스 json-server 맹글기

글이 개발자 소양이 충분한 당신의 방문을 오래도록 오래전부터 지둘린당.

 

확인했다면 서버가 돌도록 그대로 두고 vscode에서 cmd 터미널을 한개 더 열도록 하장

(아래 그림 참고하면 할 수 있을게당) 

 

 

만약 위 방식이 싫다면 vscode에서 File -> new Window로 vscode를 새창으로 1개 

더 열어서 작업하면 헷갈리지 않고 조으당. (개인적 추천 방법)

 

css가 일부 수정되어야 한다고 투덜 투덜 메세지가 비밀글로 와서 괜시리 맘이 쓰이는

관계롱 요기서 다시 새로  REACTSTUDY 아래에  rfetchaxios 폴더를 맹글어서 하장.

노파심에 나의 터미널을 복사해서 붙여본당.

D:\reactstudy>npm create vite@latest
Need to install the following packages:
create-vite@5.5.3 Ok to proceed? (y)

> npx
> create-vite

√ Project name: ... rfetchaxios
√ Select a framework: » React
√ Select a variant: » JavaScript

Scaffolding project in D:\reactstudy\rfetchaxios...

Done. Now run:

   cd rfetchaxios
   npm install
   npm run dev

D:\reactstudy>cd rfetchaxios
D:\reactstudy\rfetchaxios>npm install
D:\reactstudy\rfetchaxios>npm install -D @faker-js/faker
D:\reactstudy\rfetchaxios>npm run dev

 

초기 세팅이 같아지도록  index.css 와 App.css 파일안의 내용은  일단 전부 지워버리장.

그리고 체킁 띠작하장.

 

index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <title></title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

 

main.jsx

import { createRoot } from "react-dom/client";
import App from "./App.jsx";
import "./index.css";

createRoot(document.getElementById("root")).render(<App />);

 

App.jsx

import "./App.css";

function App() {
  return (
      <div>
        <h1>CSS는 알아서..</h1>
      </div>
  );
}

export default App;

 

요상태에서 빼먹지 말고 같이 가장. (나 자신에게 하는 말)

 

Friend.css

.friend {
    box-sizing: border-box;
    width: 150px;
    height: 250px;
    border: 5px groove blueviolet;
    display: inline-block;
    text-align: center;
    font-size: 1.5em;
    vertical-align: top;
  }
  h5 {
    margin: 0px;
    margin-bottom: 5px;
  }

 

Friend.jsx

import "./Friend.css";
import PropTypes from "prop-types";
import { faker } from "@faker-js/faker/locale/ko";

//Props 타입 정의
Friend.propTypes = {
  fid: PropTypes.string,
  name: PropTypes.string,
  age: PropTypes.number,
  avatar: PropTypes.string,
  job: PropTypes.string,
};

const avatarURL = "https://api.dicebear.com/9.x/adventurer/svg?seed=";

function Friend({ fid, name, age, avatar, job }) {
  if (!fid) {
    fid = `f${faker.number.int({ min: 100, max: 999 })}`;
    name = faker.person.firstName();
    age = faker.number.int({ min: 20, max: 99 });
    avatar = faker.person.firstName();
    job = faker.person.jobTitle().split(" ")[1];
  }

  console.log("체킁:", fid, name, age, avatar, job);

  return (
    <div className="friend">
      <img src={`${avatarURL}${avatar}`} alt="아바타" />
      <h5>{name}</h5>
      <h5>{age}살</h5>
      <h5>{job}</h5>
    </div>
  );
}

export default Friend;

 

Container.css

.container {
    width: 600px;
    min-height: 420px;
    border: 1px solid pink;
    margin: 50px auto;
    text-align: center;

  }
  .e7e {
    font-size: 4em;
    line-height: 130%;
    background-color: black;
    color:yellow;
  }

 

Container.jsx

import "./Container.css";
import Friend from "./Friend";
function Container() {
  return (
    <div className="container">
      <h1>경미니 베.푸(Very Proud)들</h1>
      <Friend />
      <Friend />
      <Friend />
      <Friend />
      <div className="e7e">&copy;E7E 만만세</div>
    </div>
  );
}

export default Container;

 

App.jsx

import "./App.css";
import Container from "./Container";

function App() {
  return (
      <div>
        <Container />
      </div>
  );
}

export default App;

 

결과 화면은  faker를 썼기 때문에 틀만 같고 내용은 다를 수 있을지어랑 .

 

Container.jsx  비동기 AJAX Promise를 리턴하는 fetch를 넣어 아래처럼 수정해 보장.

import "./Container.css";
import Friend from "./Friend";
function Container() {
  let kmFriends = [];
  fetch("http://localhost:8272/friends").then((response) => {
    response.json().then((friends) => {
      console.log("체킁:", friends);
      kmFriends = friends;
    });
  });

  return (
    <div className="container">
      <h1>경미니 베.푸(Very Proud)들</h1>
      {kmFriends.length != 0 ? <Friend /> : <h1>띤구없어용</h1>}
      <div className="e7e">&copy;E7E 만만세</div>
    </div>
  );
}

export default Container;

결과 화면을  누느로 확인한다면

당근 Friend  아니공, 띤구없어용이 뜬당. console.log에는 값이 잘 찍히지 않을 수 없당.

비동기니깡... fetch가 값을 가져오는 동안 화면이 먼저 그려졌당.(삐동기 알디용?)

 

요걸 나오게 하려면, useEffect와 useState 가 다 필요하당.

Container.jsx 를 아래처럼 수리해서 실행해 보장

import { useEffect, useState } from "react";
import "./Container.css";
import Friend from "./Friend";
function Container() {
  const [friends, setFriends] = useState([]);

  useEffect(() => {
    fetch("http://localhost:8272/friends").then((response) => {
      response.json().then((friends) => {
        console.log("체킁:", friends);
        setFriends(friends);
      });
    });
  }, []);

  return (
    <div className="container">
      <h1>경미니 베.푸(Very Proud)들</h1>
      {friends.length != 0 ? (
        friends.map((frd) => (
          <Friend
            key={frd.id}
            fid={frd.id}
            name={frd.name}
            age={frd.age}
            avatar={frd.avatar}
            job={frd.job}
          />
        ))
      ) : (
        <h1>띤구없어용</h1>
      )}
      <div className="e7e">&copy;E7E 만만세</div>
    </div>
  );
}

export default Container;

 

결과는 아래와 같을기당.

흐름 정리를 한번 해보면...

1. 리액티브 변수 friends 초기값 빈배열이어서 

2.  JSX 컴포넌트는 <h1>친구 없어용</h1>

3.  useEffect실행, 두번째 매개변수 []라서 딱 한번만 실행

4,  fetch로 값을 가져왕, setFriends호출, 리액티브 변수값 변경

5,  return 되는 jsx 컴포넌트 다시 그리깅, 이땐 friends값 존재

 

결론적으로 친구없어용 이었다가 화면이 다시 그려지는건뎅, 넘 빨리 다시 그려

안보인당.~~ ㅋㅋ. 느끼미 와야만 한당.

 

useEffect 훅(hook) 함수의 두번째 매개변수를 [] 에서 [friends]로 바꾸면 무슨 일이 일어날깡?

한번 꼭 해보았으면 좋겠당. ~~ 그리고 꼭  console.log를 보아야 한당.

결과화면은 분명 당신에게 아무일도 없는 것처럼 잔잔히 속이려 들것이다.

 

난 맘이 약하당. 결과화면에게 속은 걸 모르겠다면, 아래 소스를 가지고 해보길 바란당.

Container.jsx

import { useEffect, useState } from "react";
import "./Container.css";
import Friend from "./Friend";
function Container() {
  const [friends, setFriends] = useState([]);

  useEffect(() => {
    fetch("http://localhost:8272/friends").then((response) => {
      response.json().then((friends) => {
        console.log("체킁:", friends);
        setFriends(friends.map(friend=>{
            friend.avatar = `${friend.avatar}${Math.floor(Math.random()*100)}`
            return friend; 
      }));
      });
    });
  }, [friends]);

  return (
    <div className="container">
      <h1>경미니 베.푸(Very Proud)들</h1>
      {friends.length != 0 ? (
        friends.map((frd) => (
          <Friend
            key={frd.id}
            fid={frd.id}
            name={frd.name}
            age={frd.age}
            avatar={frd.avatar}
            job={frd.job}
          />
        ))
      ) : (
        <h1>띤구없어용</h1>
      )}
      <div className="e7e">&copy;E7E 만만세</div>
    </div>
  );
}

export default Container;

 

어쩌면 이 상태(state)관리가 당신을 힘들게 할 지도 몰랐는데,

다행히 이 부분이  요래 조래 여러가지 모듈들이 나와서 경쟁하다가 최근

결정적 우세종(?? 지금은 안 알려줄거당~~ ㅋ)이 나와서 이긴 것 같으니

걱쩡따위는 분리수거말고 그냥 태워서 흔적을 없애도 되겠당.

 

앞으로 Promise를 리턴하는 fetch 나 axios쓸꺼이기 때문에 혹 아직 Promise를 모른다면

2024.01.08 - [자바스크립트] - Promise(약속) 모르면 바보옹(비동기)

글을 꼬옥 읽고, 욘습도 하고 다시 만나길 기대해본당.

 

이런...  오늘은 일요일이당.   그냥 막 ㅃㅃ2


 

본능으로 부터 embedded 된  감정과 이성이 있고,

 

태어난 이후로 학습된 감정과 이성이 있당.

 

이 두 아이는  화합하는 경우도 있지만, 모순으로 서로 참  많이도 싸운당. 

 

내 안에서 조차 이러할 진데, 다른 사람의 감정과 이성에 동기화 하려면,

 

공감 받으려면, 그 노력이 나만 손해 보는 느끼미당.

 

저울의 평형상태를 만들려 시간을 낭비하지 말고

 

때론 더 빠르게, 때론 더 느리게... 때론 더 천천히

 

그냥 저울을 흔들어라..

 

그 파동이  푸리에 방정식으로 당신의 상상을  더 하거나 빼 줄거시당. 

 

운이 좋다면 공명으로 금수저를 만나게 될지동...... 

 

https://www.youtube.com/watch?v=m0o7fbNKhpM

 

관련글 더보기