WEB/React

[영화 웹] #7. PRACTICE MOVIE APP

Harimad 2022. 1. 29. 14:27

노마더코드 깃 히스토리: https://github.com/nomadcoders/react-for-beginners/commits/master

#7.0 To Do List part One

목표: input에서 todo를 입력하면 배열에 data를 담아주는 state를 만들어본다.

 

form은 submit이벤트(새로고침)를 갖고 있다. 그러므로 evernt.preventDefault() 함수를 이용하여 기본 동작을 막는다.
const [toDos, setToDos] = useState([]); -> 기본값은 비어있는 배열
state는 직접적으로 수정이 불가능하다 ex) : toDo = “” (X)
함수를 써서 수정해야한다. ex) : setToDo = (“”) (O)
그래서 toDos 배열을 수정하고 싶다면 함수를 써야한다.

setToDos(currentArray => [toDo, ...currentArray]);
- spreadOperator로  currentArray 배열에 toDo를 추가 시켜준다.

- currentArray는 toDos를 말하므로 처음엔 빈배열이 들어있다.

- setTodo함수로 toDo 값이 입력되면 setToDos함수에 의해서 toDos배열 앞에서 부터 toDo가 채워진다.

 

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);
  };
  return (
    <div>
      <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your TODO"
        ></input>
        <button>Add To Do</button>
      </form>
    </div>
  );
}

 

한 가지 궁금한점

toDos를 console에 찍어볼때 onSubmit 함수안에서 찍으면 해당 toDo가 빠진상태로 출력이 된다.

다음에 다시 onSubmit을 하면 이전 배열이 나오는데

왜 그럴까? -> setState가 비동기이기때문

setToDos(currentArray => [toDo, ...currentArray]);
setToDo('');
console.log(toDos);
//첫submit:  빈배열 출력(0개출력), 하지만 toDos의 배열에는 data가 들어간상태(길이1)
//두번째submit: 이전에 입력한 toDo가 출력(1개출력), 하지만 toDos는 data가 또 들어감(길이2)

간단한 해결책

setToDos(currentArray => {
    const newArray = [toDo, ...currentArray];
    console.log(newArray); 
    return newArray;
});

 

참고할 자료들

https://reactjs.org/docs/faq-state.html  When is setState asynchronous?

 

 

Component State – React

A JavaScript library for building user interfaces

reactjs.org

https://stackoverflow.com/questions/36085726/why-is-setstate-in-reactjs-async-instead-of-sync

 

Why is setState in reactjs Async instead of Sync?

I have just found that in react this.setState() function in any component is asynchronous or is called after the completion of the function that it was called in. Now I searched and found this blog (

stackoverflow.com

 

#7.1 To Do List part Two

App컴포넌트에 아래만 추가 해주면 된다. map함수는 아래 링크 참고

  <ul>
    {toDos.map((item, index) => (
      <li key={index}>{item}</li>
    ))}
  </ul>

map: https://devdocs.io/javascript/global_objects/array/map

https://ko.reactjs.org/docs/lists-and-keys.html

 

리스트와 Key – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

TODO삭제버튼 기능이 들어간 중간 완성본

filter를 이용해서 배열요소를 정리하면 Button기능을 구현할 수 있다.

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('');
  };
  const deleteBtn = index => {
    setToDos(toDos.filter((item, todoIndex) => index !== todoIndex));
  };
  return (
    <div>
      <h1>My To Dos ({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="Write your TODO"
        ></input>
        <button>Add To Do</button>
      </form>
      <hr></hr>
      <ul>
        {toDos.map((item, index) => (
          <li key={index}>
            {item}
            <button onClick={() => deleteBtn(index)}>❌</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

 

 

#7.2 Coin Tracker

URL파일을 fetch후 JSON으로 변환한 이후에 useState에 값을 넣는다.

그 값을 map함수로 option Tag에 보여주도록 만든다.

import { useEffect, useState } from 'react';

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

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

  const onChange = event => {
    setDollar(event.target.value);
  };

  return (
    <div>
      <h1>The Coins {loading ? '' : `(${coins.length})`}</h1>
      <p>Coin Price</p>
      {loading ? (
        <strong>Loding...</strong>
      ) : (
        <select>
          {coins.map(coin => (
            <option>
              {coin.name}({coin.symbol}): ${coin.quotes.USD.price} {coin.symbol}
            </option>
          ))}
        </select>
      )}

      <br></br>
      <br></br>
      <hr></hr>

      <p>Coins You can buy</p>
      <span>Your dollars: </span>
      <input value={dollar} onChange={onChange} type="number"></input>
      <span>$ </span>

      <br></br>
      {loading ? (
        <strong>Loading...</strong>
      ) : (
        <select>
          {coins.map(coin => (
            <option>
              {coin.name} ({coin.symbol}): {dollar / coin.quotes.USD.price}{' '}
              {coin.symbol}
            </option>
          ))}
        </select>
      )}
    </div>
  );
}

export default App;

 

fetch로 JSON파일 읽어오기 연습 참고링크

https://velog.io/@eunjin/JavaScript-fetch-%ED%95%A8%EC%88%98-%EC%93%B0%EB%8A%94-%EB%B2%95-fetch-%ED%95%A8%EC%88%98%EB%A1%9C-HTTP-%EC%9A%94%EC%B2%AD%ED%95%98%EB%8A%94-%EB%B2%95

 

[JavaScript] fetch 함수 쓰는 법, fetch 함수로 HTTP 요청하는 법

fetch 함수는 XMLHttpRequest 객체보다 최근에 나온, HTTP 요청 전송 기능을 제공하는 Web API다. 데이터를 받아오기 위해 습관처럼 쓰던 fetch에 대해 정리해보았다.

velog.io

https://ko.javascript.info/fetch

 

fetch

 

ko.javascript.info