노마드코더 ReactJS로 영화 웹 서비스 만들기 7 (실전편)

딩쓰·2022년 12월 17일
0
post-thumbnail

7. PRACTICE MOVIE APP

#7.0~ 7.2 React를 이용해 간단한 To-Do를 만들어 보자!

To Do List

초기 세팅

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

export default App;
import { useState } from 'react';

function App() {
  const [toDo, setToDo] = useState('');
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if(toDo === "") { //input이 비어 있으면 함수를 실행시키지 않음
      return;
    }
    setToDo(""); // input을 비워줌
  };
  
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input 
           onChange={onChange} 
           value={toDo} 
           type="text" 
           placeholder="Write your to do..." 
         />
        <button>Add To Do</button>
      </form>
    </div>
  );
}

export default App;
  • input값을 컨트롤 하는 방법
  1. const [toDo, setToDo] = useState('');로 디폴트값을 ''로 해줌
  2. inputvaluetoDo를 주고, onChange를 넣는데 onChange함수를 만들어서 넣어줌.
  3. <form>태그를 만들어 input이랑 <button> 태그를 넣어줌
    ⭐️ <form>은 submit 이벤트를 갖고 있어서 <button>을 누르면 <form>이 submit되고 새로고침됨.
  4. form 태그의 새로고침을 막기 위해서 event.preventDefault();를 사용해야함
  5. toDo의 값이 변할 때마다 변경함수인 setToDo가 값을 갱신해줌.

todo를 todos에 배열로 담기

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") { //input이 비어 있으면 함수를 실행시키지 않음
      return;
    }
    setToDos((currentArray) => [toDo, ...currentArray]);
    setToDo(""); // input을 비워줌
  };

  console.log(toDos);
  return (
    <div>
      <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your to do..."
        />
        <button>Add To Do</button>
      </form>
    </div>
  );
}
  • 이제 해야할 것은 여러개의 toDo를 받을 수 있는 array를 만드는 것임
  • const [toDos, setToDos] = useState([]); 코드를 작성해줌
  • 일반적인 JS에서라면 toDos.push를 했을거지만, 여기선 절대로 state를 직접적으로 수정하면 안됨!
    => 변경함수를 사용해서 변경해야함
  • setToDos((currentArray) => [toDo, ...currentArray]); : 첫번째 argument로 현재의 state를 받아서 toDo의 저장되어있는 값과 빈array인 toDos를 합쳐서 하나의 array로 만듬.
  • ...currentArray -> 구조분해할당해서 괄호를 벗김.

state 변경 함수를 사용할 때는 2가지 옵션이 있음
1. setToDo("") : 이런식으로 단순히 값을 직접 넣는것
2. setToDos((currentArray) => [toDo, ...currentArray]) : 함수를 보내는 방법

.map() 함수로 todo리스트 목록 출력하기

  • 위에 처럼 toDos배열이 이것저것 많이 가지고 있는데 이것들을 component로 만들어 볼거임.
    => 어떻게? map함수를 사용해서!

  • .map() 함수: 함수의 첫번째 argument로 현재의 요소들(item)을 가져와서 조건에 맞게 새로운 array로 출력하는 함수. array 요소의 갯수만큼 출력함.
function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") {
      return;
    }
    setToDos((currentArray) => [toDo, ...currentArray]);
    setToDo("");
  };

  console.log(toDos);
 
  return (
    <div>
      <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your to do..."
        />
        <button>Add To Do</button>
      </form>
      <hr />
      <ul>
        {toDos.map((item) => (
          <li >{item}</li>
        ))}
      </ul>
    </div>
  );
}
  • 위와 같이 .map()함수를 작성하면 list가 출력됨
  • But! 이렇게 하면 콘솔창에 경고가 뜸

콘솔창에 뜬 경고문구 해결하기

  • 위의 콘솔에서 말하는것은 같은 component의 list를 render할 때 key라는 prop을 넣어줘라는 뜻
    => 리액트가 기본적으로 list에 있는 모든 item들을 인식하기 때문
<ul>
  {toDos.map((item, index) => (
    <li key={index}>{item}</li>
  ))}
</ul>
  • key 속성을 넣어주면 해결됨! key는 고유의 값(unique)이야 함.
  • .map()의 두번째 argument에는 index가 들어갈 수 있는데 (숫자로된) 이값을 사용해 key값을 넣어줌.

✅ 결과화면

  • 입력한 list가 잘 출력되는걸 볼 수있음

to-do-list 최종코드

//App.js
import { useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") {
      return;
    }
    setToDos((currentArray) => [toDo, ...currentArray]);
    setToDo("");
  };

  console.log("toDos의 현재값", toDos);

  return (
    <div>
      <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your to do..."
        />
        <button>Add To Do</button>
      </form>
      <hr />
      <ul>
        {toDos.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

Coin Tracker 초기 세팅

💡 이제 간단하게 암호화폐(코인)들과 그 가격을 나열하는 것을 할거임

첫번째로 할 것은, 페이지나 처음 들어왔을 때 로딩 메세지가 보이게 하는것

import { useState } from 'react';

function App() {
  const [loading, setLoading] = useState(true);
  return (
    <div>
      <h1>The Coins</h1>
      {loading ? <strong>Loading...</strong> : null}
    </div>
  );
}

export default App;
  • loading의 초기값은 true
  • 그래서 <strong>Loading...</strong> 를 화면에 출력해주고 있음
  • 만약 loading이 아니라면 아무것도 보여주지 않을거임.

fetch로 API 불러오기

import { useState, useEffect } from 'react';

function App() {
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    fetch('https://api.coinpaprika.com/v1/tickers')
      .then((response) => response.json()) 
      .then((json) => console.log(json));
  }, []); //빈배열은 처음 한번만 실행됨.
  
  return (
    <div>
      <h1>The Coins</h1>
      {loading ? <strong>Loading...</strong> : null}
    </div>
  );
}
  • coinpaprika에서 코인 관련 정보 API를 가져올거임.
  • .then((response) => response.json()):받아온 response를 json형식을 추출해옴.

  • 콘솔의 network에 들어가면 200 ok로 response를 잘 받아온것을 확인할 수 있음.

  • 콘솔창에서 fetch로 data를 array로 받아온걸 확인 할 수 있음

이제 이 data를 우리의 component에서 어떻게 보여줄 수 있을까?
-> data를 useState()를 이용해 변경함수에 담아준다!

coins 변수에 코인 arrary 담기

function App() {
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([])
  
  useEffect(() => {
    fetch('https://api.coinpaprika.com/v1/tickers')
      .then((response) => response.json()) 
      .then((json) => {
        setCoins(json); //변경함수에 data를 넣어줌
        setLoading(false); 
   //coins 얻기를 끝냈다면 loading을 false로 바꿔줌
      });
  }, []);
  
  return (
    <div>
      <h1>The Coins</h1>
      {loading ? <strong>Loading...</strong> : null}
    </div>
  );
}
  • 받아온 JSON 파일을 변경함수 setCoins에 담아줌
  • coins 얻기를 끝냈다면 loading을 false로 바꿔줌

💡 이제 우리는 coins라는 변수에 코인들의 array가 담겨있다는 것을 알고 있음. 어떻게 할까?
=> .map() 을 사용하자!

.map()으로 화면에 출력하기

function App() {
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([]);
  
  useEffect(() => {
    fetch('https://api.coinpaprika.com/v1/tickers')
      .then((response) => response.json()) 
      .then((json) => {
        setCoins(json);
        setLoading(false);
      });
  }, []);
  
  return (
    <div>
      <h1>The Coins ({coins.length})</h1>
      {loading ? <strong>Loading...</strong> : null}
      <ul>
        {coins.map((coin) => (
          <li>
            {coin.name} ({coin.symbol}) : ${coin.quotes.USD.price} USD
          </li>
        ))}
      </ul>
    </div>
  );
}
  • useState()의 기본값을 빈배열로 만들어서 undefined가 반환되지 않게 해야함
    => coins.length에서 오류가 나지않게 하기 위해
  • coins안에 들은 코인 배열들을 ul태그로 화면에 출력해줌
  • coin.원하는것 으로 원하는 속성만 골라서 출력해줄 수 있음.

select 태그로 바꾸고, loading일 때는 코인 개수 숨기기

function App() {
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([]);

  useEffect(() => {
    fetch("https://api.coinpaprika.com/v1/tickers")
      .then((response) => response.json())
      .then((json) => {
        console.log(json);
        setCoins(json);
        setLoading(false);
      });
  }, []);

  return (
    <div>
      <h1>The Coins {loading ? "" : `(${coins.length})`}</h1>
      {loading ? (
        <strong>Loading...</strong>
      ) : (
        <select>
          {coins.map((coin) => (
            <option key={coin.id}>
              {coin.name} ({coin.symbol}): ${coin.quotes.USD.price} USD
            </option>
          ))}
        </select>
      )}
    </div>
  );
}
  • loading 일 때는 코인개수가 안보이게 JS를 통해서 코드를 작성해줌
  • 원래 {loading ? <strong>Loading...</strong> : null} null이였던 자리에 select태그로 바꾼 코드로 바꿔줌
  • 원래는 loading이 false로 바뀌면서 null이 실행 되었는데 null에 코드를 넣어줘서 이제는 코인select박스가 보일 것임

✅ 결과화면

Coin Tracker 최종코드

import { useEffect, useState } from "react";

function App() {
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([]);

  useEffect(() => {
    fetch("https://api.coinpaprika.com/v1/tickers")
      .then((response) => response.json())
      .then((json) => {
        console.log(json);
        setCoins(json);
        setLoading(false);
      });
  }, []);

  return (
    <div>
      <h1>The Coins {loading ? "" : `(${coins.length})`}</h1>
      {loading ? (
        <strong>Loading...</strong>
      ) : (
        <select>
          {coins.map((coin) => (
            <option key={coin.id}>
              {coin.name} ({coin.symbol}): ${coin.quotes.USD.price} USD
            </option>
          ))}
        </select>
      )}
    </div>
  );
}

export default App;
profile
Frontend Developer

0개의 댓글