React 클라이언트 Ajax 요청

이유정·2022년 10월 12일
0

코드스테이츠 TIL

목록 보기
31/62
post-thumbnail

React 데이터 흐름에 대해 다시 알아보자.

React 데이터 흐름

React 데이터 흐름

-react는 컴포넌트 단위다.
-상향식으로 만든다. (테스트가 쉽고, 확장성이 좋다)
-컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 전달인자혹은 속성처럼 전달받을 수 있다.
-데이터를 전달하는 주체는 부모 컴포넌트다. (데이터 흐름이 하향식이다./ 단방향 데이터 흐름)
-컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 모른다.
-사용자 입력은 이벤트에 따라 변할 수 있다 (state)
-만일 하나의 상태가 두 컴포넌트의 영향을 받는다면, 공동 컴포넌트를 찾아 그곳에 위치시킨다.

State 끌어올리기

-부모 컴포넌트에서의 상태가 하위 컴포넌트에 의해 변한다.
-하위 컴포넌트에서의 클릭 이벤트가, 부모의 상태를 바꾼다.
-상태를 변경시키는 함수를 하위 컴포넌트에 props로 전달해서 해결할 수 있다.
-하위 컴포넌트는 상위 컴포넌트로부터 전달받는 데이터의 타입이 무엇인지만 알 수 있다. 데이터가 state로부터 왔는지, 하드코딩으로 입력한 내용인지는 알지 못한다.
-상위 컴포넌트의 상태를 변경하는 함수 그 자체를 하위 컴포넌트로 전달하고 이 함수를 하위 컴포넌트가 실행한다.

예제1)
: 상태를 변경하는 함수는 handleChangeValue이고, 전달은 props를 이용하자.
props이름은,, 하위 컴포넌트가 버튼 클릭 이벤트에 따라 상태를 변경하려고 하므로 이름은 handleButtonClick 이다.

import React, {useState} from 'react'; 

export default function ParentComponent(){
  const [value, setValue] = useState("날 바꿔봐");
  
  const handleChangeValue = () =>{
    setValue("보여줄게 달라진 값")
};
  
  return (
  	<div>
    	<div>값은 {value}입니다 </div>
		<ChildComponent handleButtonClick={handleChangeValue}/>
    </div>
  );
}

function ChildComponent({handleButtonClick}){
	const handleClick = () =>{
      handleButtonClick()
    };
  return <button onClick={handleClick}>값 변경</button>;
}

State와 생명주기

React로 생각하기


여러 컴포넌트 사이에서 어떤 방식들로 데이터를 다룰지 배워보자.
Effect Hook과 Ajax를 사용해 서버로부터 데이터를 받아오는 방법에 대해 배우자.

Effect Hook

Side Effect

  • 함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect가 있다고 한다. (React에서는 컴포넌트 내에서 fetch를 사용해 API정보를 가져오거나 이벤트를 활용해 DOM 을 직접 조작할 때 )

보통 React 애플리케이션 작성할때, AJAX 요청이 필요하거나,fetch API, LocalStorage, 타이머(setTimeout)와 같은 api를 사용하는 경우가 발생할 수 있다. 이것들은 Side Effect이며, 이를 다루기 위해 Effect Hook 을 제공한다.

Pure Function

순수함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 것. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 것은 순수함수가 아니다.

  • 어떠한 전달 인자가 주어질 경우, 항상 똑같은 값이 리턴된다. (예측가능함수)

Effect Hook 기본

useEffect는 컴포넌트 내에서 Side effect 를 실행할 수 있게 하는 Hook이다.
useEffect의 첫번째 인자는 함수다. 해당 함수 내에서 sideEffect를 실행하면 된다.
sideEffect는 언제 실행될까?

  • 컴포넌트가 새롭게 렌더링 될 때 Effect Hook 이 실행된다.
    -컴포넌트 생성 후 처음 화면 렌더링 될 때
    -컴포넌트에 새로운 props가 전달되며 렌더링 될 때
    -컴포넌트에 상태(state)가 바뀌면 렌더링 될 때
useEffect(() => {
	console.log(몇 번 호출될까요?)
})
//컴포넌트가 처음 생성되거나, props가 업데이트 되거나, state가 업데이트 될 때마다 실행됩니다.
useEffect(() => {
	console.log(몇 번 호출될까요?)
},[])
//컴포넌트가 처음 생성될 때만 함수가 실행됩니다.
useEffect(() => {
	console.log(몇 번 호출될까요?)
},[dep])
//dep이 업데이트 될 때마다 실행됩니다.

Hook을 쓸 때 주의할 점

  • 최상위에서만 Hook을 호출한다.
  • React 함수 내에서 Hook을 호출한다.

Effect Hook 조건부 실행

useEffect의 두번째 인자는 '배열'이다. (종속성 배열이라고 한다.)
이 배열의 조건은 '어떤 값의 변경이 일어날 때'이다.
따라서 밑 예시에서 해당 배열엔 '어떤 값'의 목록이 들어간다.

링크텍스트

  • 명언 목록 (proverbs)
  • 필터링할 문자열 (effect)
  • 카운트 (count)

이 예제는 filter가 변할 때에만, effect 함수가 실행된다.
한편, 카운트를 올리는 버튼은 아무리 눌러도 effect함수가 실행되지 않는다.
왜냐? 종속성배열에 filter만 존재하고 count는 존재하지 않기 때문이다.

이정도 코드는 외우는게 좋을 것 같다!!

import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";

export default function App() {
  const [proverbs, setProverbs] = useState([]);
  const [filter, setFilter] = useState("");
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log("언제 effect 함수가 불릴까요?");
    const result = getProverbs(filter);
    setProverbs(result);
  }, [filter]);

  const handleChange = (e) => {
    setFilter(e.target.value);
  };

  const handleCounterClick = () => {
    setCount(count + 1);
  };

  return (
    <div className="App">
      필터
      <input type="text" value={filter} onChange={handleChange} />
      <ul>
        {proverbs.map((prvb, i) => (
          <Proverb saying={prvb} key={i} />
        ))}
      </ul>
      <button onClick={handleCounterClick}>카운터 값: {count}</button>
    </div>
  );
}

function Proverb({ saying }) {
  return <li>{saying}</li>;
}

API

useEffect(함수,[종속성1, 종송석2,...])
useEffect 의 두번째 인자는 종속성 배열이다. 배열 내의 종속성1, 또는 종속성2의 값이 변할 때 , 첫번째 인자의 하수가 실행된다.
배열 내의 어떤 값이 변할 때만, effect가 발생하는 함수가 실행된다.

컴포넌트 내에서의 AJAX 요청

useEffect(()=>{
  fetch(`http://서버주소/proverbs?q=${filter}`)
    .then(resp=>resp.json())
    .then(result =>{
		setProverbs(result);    
    });
  }, [filter]);

####AJAX 요청이 매우 느릴 경우?
: 로딩화면 구현은 필수적! -> 상태 처리 필요!

const [isLoading, setIsLoading] = useState(true);
// 생략 
return {isLoading ? <LoadingIndicator> : <div>로딩 완료 화면</div>}
useEffect(()=>{
	setIsLoading(true);
  fetch(`http://서버주소/proverbs?q=${filter}`)
  	.then(resp=> resp.json())
    .then(result =>{
  		setProverbs(result)
        setIsLoading(false);
  });
},[filter])

틀린 퀴즈

1) React에서 Ajax 요청을 보낼 때는 Effect Hook을 사용할 수 있다.

  • 서버로 네트워크 요청을 보낼 때, AJAX 요청을 처리한다.
  • Side effect 를 최소화하기 위해 Effect Hook을 사용한다.
  • 만약 훅을 사용하지 않고 네트워크 요청을 하면 그동안 페이지가 멈추거나 깜빡일 수 있음

2) 함수 내에서 Ajax 요청을 할 때 외부 상태를 바꾸기 때문에 순수함수가 아니다!!

3)
A. sum 함수가 외부의 변수인 c를 사용하였습니다. 이 경우 인자로 받아오지 않은 변수 c가 변함에 따라 함수의 결괏값이 달라지므로 순수 함수가 아닙니다.

let c = 12;
function sum(a, b){
	return a + b + c
}

4) Effect hook에 대한 설명으로 옳지 않은 것을 고르세요.

React 함수 내에서만 호출해야 한다.-> 맞음!!!

일반적으로 반복문, 조건문 내부에서도 사용한다. -> 틀림!!!

  • Hook의 규칙에 위배됩니다. React Hook은 최상위에서만 호출해야 합니다. 그래야만 컴포넌트가 렌더링 될 때마다 항상 동일한 순서의 Hook 호출이 보장됩니다. 만약 반복문 또는 조건문 내부에서 Hook을 사용하게 되면, React가 올바르게 각 Hook의 상태를 유지할 수 없게 됩니다.

5) 상태 끌어올리기에 대한 설명으로 옳지 않은 것을 고르세요.

하위 컴포넌트에서 정의된 state를 상위 컴포넌트로 전달하는 것을 말한다.-> 틀림

  • 상위 컴포넌트에서 정의된 state 갱신 함수를 하위 컴포넌트로 전달하여 호출합니다. 이 보기는 완전히 틀린 보기입니다. 리액트는 일반적으로 하위 컴포넌트에서 정의된 state를 상위로 전달하지 않습니다.

6)map 함수의 key prop을 지정할 때에는 일반적으로 Math.random() 메서드를 사용한다.(틀림!!!!!!)

  • map 함수로 배열 형태로 저장된 여러 엘리먼트들을 렌더링하는 경우가 많습니다. 이 때, 각각의 최상위 엘리먼트들에 key prop이 요구됩니다. 이는 React가 해당 엘리먼트들의 변경 사항을 알아채기 쉽게 돕기 위함입니다.
    Math.random()을 사용하게 되면 key가 예상 불가능하며, 시시각각 변화하게 됩니다. 그렇게 되면 React는 많은 컴포넌트 인스턴스와 DOM 노드를 불필요하게 리렌더링하고, 이에 따라 성능 이슈가 발생하거나 자식 컴포넌트의 state가 유실될 수 있습니다.
profile
팀에 기여하고, 개발자 생태계에 기여하는 엔지니어로

0개의 댓글