ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React.js] React 기초5 (+ useEffect, fetch, react Hooks, useNavigate, PUT, DELETE, POST)
    React 2022. 10. 30. 17:25

    * 렌더링 : 리액트에서는 컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업이다.

     

    DayList.js

    import { useEffect,useState } from "react";
    import { Link } from "react-router-dom";
    import dummy from "../db/data.json";
    
    export default function DayList(){
        const [days, setDays]=useState([]);
        // API에서 데이터를 갖고와서 바꿔주는 방식으로 하겠다
        // 따라서 데이터가 바뀌면 자동으로 렌더링 될 것이다.
        const [count, setCount] = useState(0);
    
        function onclick(){
            setCount(count+1);
        }
    
        function onclick2(){
            setDays([
                ...days,
                {
                    id:Math.random(),
                    day:1,
                }
            ])
        }
    
        useEffect(()=>{
            console.log("Count change")
        }, [count]);
        // 어떤 상태값이 바뀌었을 때 동작하는 함수를 작성할 수 있다.
        // 두번째 매개변수를 넣어주면, 그 매개변수(의존성 배열)가 바뀌었을 때만, 함수가 실행된다.
        // 이것을 의존성 배열이라고 한다.
        // 즉, 여기서는 카운드 값이 바뀔 때만 콘솔로그가 실행된다.
    
        return (
            <>
                <ul className="list_day">
                {days.map(day=>(
                    <li key={day.id}>
                        <Link to={`/day/${day.day}`}>Day {day.day}</Link>
                        {/* day.day는 data.json파일의 days 객체에서 day키값이 가진 값이다. */}
                    </li>
                ))}
                </ul> 
                <button onClick={onclick}>{count}</button>
                <button onClick={onclick2}>day change</button>
            </>
            
        );
    }
    // 맵은 배열을 받아서 또다른 배열로 반환해주는 것인데, 
    // 이떄 반환되는 요소를 JSX 형태로 작성해주면 된다.
    // key 반복되는 요소의 고유한 값으로 전달해야 되서 여기서는 day.id

     

    * API 비동기 통신 : 

    동기 통신은 전체 페이지를 reload하기 때문에, 서버의 부하가 커지고 시간도 오래 걸린다. 또한 페이지가 리로드 되는 동안에는 다른 데이터를 처리할 수 없다. 반대로 비동기 통신은 요청을 보낸 후에는 응답과는 상관없이 동작한다.

     

    * AJAX : Asynchronous JavaScript and XML 으로, 빠르게 동작하는 동적인 웹 페이지를 만들기 위한 개발 기법이다. 비동기성으로 페이지 전체를 리로드 하지 않고, 사용자의 이벤트가 발생하면 페이지의 일부만 업데이트한다. 서버와의 통신을 위해 XMLHttpRequest 객체를 사용한다. JSON, XML, HTML, 일반 텍스트 등 다양한 포맷을 주고 받을 수 있다. 

     

    * Fetch API : XMLHttpRequest를 대체하며 비동기 http 요청을 좀 더 쓰기 편하게 해주는 API이다. 첫번째 인자는 URL, 두 번째 인자는 옵션 객체를 받는다. Promise 기반으로 동작하며 fetch의 기본 응답 결과는 Response 객체이다.

     

    DayList.js

    import { useEffect,useState } from "react";
    import { Link } from "react-router-dom";
    import dummy from "../db/data.json";
    
    export default function DayList(){
        const [days, setDays]=useState([]);
        // API에서 데이터를 갖고와서 바꿔주는 방식으로 하겠다
        // 따라서 데이터가 바뀌면 자동으로 렌더링 될 것이다.
        
        // 렌더링이 완료되고, 후에 최초 한번만 API를 호출해주면 된다.
        // 이때는 의존성 배열에 빈 배열을 전달해주면 된다.
        useEffect(()=>{
            fetch('http://localhost:3001/days') // API경로를 적어주면, 프로미스가 반환된다.
            .then(res => { //그러면 then을 이용해서 리턴해준다.
                return res.json() //여기서 리스폰스는 http 응답이기 때문에, json으로 바꿔준다.
            })
            .then(data=>{
                setDays(data);
            })
        }, []);
        // 어떤 상태값이 바뀌었을 때 동작하는 함수를 작성할 수 있다.
        // 두번째 매개변수를 넣어주면, 그 매개변수(의존성 배열)가 바뀌었을 때만, 함수가 실행된다.
        // 이것을 의존성 배열이라고 한다.
        // 즉, 여기서는 카운드 값이 바뀔 때만 콘솔로그가 실행된다.
    
        return (
            
            <ul className="list_day">
            {days.map(day=>(
                <li key={day.id}>
                    <Link to={`/day/${day.day}`}>Day {day.day}</Link>
                    {/* day.day는 data.json파일의 days 객체에서 day키값이 가진 값이다. */}
                </li>
            ))}
            </ul> 
                
            
        );
    }
    // 맵은 배열을 받아서 또다른 배열로 반환해주는 것인데, 
    // 이떄 반환되는 요소를 JSX 형태로 작성해주면 된다.
    // key 반복되는 요소의 고유한 값으로 전달해야 되서 여기서는 day.id

    Day.js

    import dummy from "../db/data.json"; //더미 데이터 임포트
    import { useParams } from "react-router-dom";
    import Word from "./Word";
    import { useEffect } from "react";
    // url이 포함된 값을 얻을 때는 userParams 를 사용
    
    export default function Day(){
        //dummy.words
        const day=useParams().day;
        //const wordList = dummy.words.filter(word=>word.day===Number(day));
        //dummy.words 에서 날짜가 1인 것만 필터를 통해서 출력하겠다
        const [words, setWords]=useState([]);
    
        useEffect(()=>{
            fetch('http://localhost:3001/words') // API경로를 적어주면, 프로미스가 반환된다.
            .then(res => { //그러면 then을 이용해서 리턴해준다.
                return res.json() //여기서 리스폰스는 http 응답이기 때문에, json으로 바꿔준다.
            })
            .then(data=>{
                setDays(data);
            })
        }, []);//빈 배열을 넣어서 한번만 실행
    
        return <>
        <h2>Day {day}</h2>
        <table>
            <tbody>
                {words.map(word=>(
                    <Word word={word} key={word.id} />
                ))}
                
            </tbody>
        </table>
        </>
    }

     

    * react js code snippets 이라는 vs code 확장 플러그인으로 단축키를 이용해 쉽게 코드를 작성할 수 있다.

    rsf -> 함수형 컴포넌트 

     

    form 태그로 감싸져 있어서, 저장 버튼을 누르면 페이지 전체가 새로고침이 된다.

    반드시 저장을 해야 자동으로 렌더링이 된다.

     

    CreateWord.js

    import useFetch from "../hooks/useFetch";
    import {useRef, useState} from "react";
    import { useNavigate } from "react-router-dom"; 
    
    export default function CreateWord() {
        const days=useFetch("http://localhost:3002/days");
        const navigate = useNavigate();
        const [isLoading, setIsLoading] = useState(false);
    
        function onSubmit(e){
            e.preventDefault(); //새로고침되지 않도록 기본기능을 막음
    
            if(!isLoading){
            setIsLoading(true);
            fetch(`http://localhost:3002/words/`, {
                method:"POST",
                headers:{
                    "Content-Type":"application/json",
                },
                body: JSON.stringify({
                    day : dayRef.current.value,
                    eng : engRef.current.value,
                    kor : korRef.current.value,
                    //current 속성을 이용해서 해당 요소에 접근하고, value로 인풋에 저장된 값을 가져왔다
                    isDone : false
                }),
            })
            .then(res=>{
                if(res.ok){
                    alert("생성이 완료 되었습니다!")
                    navigate(`/day/${dayRef.current.value}`)
                    setIsLoading(false);
                }
            })
        }
        }
    
        const engRef = useRef(null);
        const korRef = useRef(null);
        const dayRef = useRef(null);
        //useRef는 돔에 접근하여, 스크롤 위치를 확인하거나 포커스를 줄 때 사용할 수 있다.
    
        return (
            <form onSubmit={onSubmit}>
                <div className="input_area">
                    <label>Eng</label>
                    <input type="text" placeholder="computer" ref={engRef}/>           
                </div>
                <div className="input_area">
                    <label>Kor</label>
                    <input type="text" placeholder="컴퓨터" ref={korRef}/>           
                </div>
                <div className="input_area">
                    <label>Day</label>
                    <select ref={dayRef}>
                        {days.map(day=>(
                        <option key={day.id} value={day.day}>
                            {day.day}    
                        </option> 
                        ))}
                    </select>         
                </div>
                <button
                style={{
                    opacity : isLoading ? 0.3 : 1
                }}
                >{isLoading ? "Saving..." : "저장"}</button>
            </form>
              
        );
    }

    CreateDay.js

    import useFetch from "../hooks/useFetch"
    import { useNavigate } from "react-router-dom"; 
    
    export default function CreateDay(){
        const days=useFetch("http://localhost:3002/days");
        const navigate = useNavigate();
        function addDay(e){
            
            fetch(`http://localhost:3002/days/`, {
                method:"POST",
                headers:{
                    "Content-Type":"application/json",
                },
                body: JSON.stringify({
                    day : days.length+1
                }),
            })
            .then(res=>{
                if(res.ok){
                    alert("생성이 완료 되었습니다!")
                    navigate(`/`)
                }
            })
    
        }
        return (
            <div>
                <h3>현재 일수 : {days.length}</h3>
                <button onClick={addDay}>Day 추가</button>
            </div>
        )
        
    }

     

     

    외부 참조 링크

    https://www.youtube.com/watch?v=SMKRXZljBt8&list=PLZKTXPmaJk8J_fHAzPLH8CJ_HO_M33e7-&index=12 

    https://yceffort.kr/2022/04/deep-dive-in-react-rendering

     

    Home

    yceffort

    yceffort.kr

    https://velog.io/@dasssseul/JS-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%86%B5%EC%8B%A0-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0XHR%EA%B3%BC-Fetch-API

     

    [JS🐣] 비동기 통신 이해하기(XHR과 Fetch API)

    브라우저에서 폼을 채우고 이를 웹 서버로 제출(submit)하면 웹 서버는 요청된 내용에 따라서 데이터를 가공하여 새로운 웹페이지를 작성하고 응답으로 되돌려준다.전체 페이지를 reload하기 때문

    velog.io

    https://ossam5.tistory.com/93

     

    [VS CODE] Reactjs Code Snippets

    ## Reactjs Code Snippets의 단축키 단축키 설명 rcc 클래스 컴포넌트 생성 rrc 클래스 컴포넌트와 react-redux 리덕스를 연결해서 생성 rccp 클래스 컴포넌트와 prop type들을 클래스 뒤에 생성 rcjc import와 e..

    ossam5.tistory.com

     

    댓글

Just do Justin