[TIL] 객체 / 배열 복사

우기·2023년 3월 31일
0
post-thumbnail

📒 오늘 공부한 내용

🔍수업목차

[15-1] 객체 / 배열 복사
[15-2] 댓글 수정하기
[15-3] 무한스크롤

✅ 객체 / 배열 복사


  • javascript에서 데이터를 복사할 때, 두 가지 개념이 존재합니다.

  • 얕은 복사(Shallow Copy)깊은 복사(Deep Copy)다.

📂 데이터 복사

let aaa = "철수"
let bbb = aaa

console.log(aaa) // 철수
console.log(bbb) // 철수

복사본의 값을 변경해서 재할당

bbb = "영희"

console.log(aaa) // 철수
console.log(bbb) // 영희

📂 객체 복사

let child1 = {
	name: "철수",
	age: 8,
	school: "다람쥐초등학교"
}
let child2 = child1

child2 // {name: '철수', age: 8, school: '다람쥐초등학교'}

복사본 child2 객체의 name 값을 변경

child2.name = "영희"

child1 // {name: '영희', age: 8, school: '다람쥐초등학교'}
child2 // {name: '영희', age: 8, school: '다람쥐초등학교'}
  • child2의 name 값만 변경했는데, child1의 name값도 변경됨

  • 자바스크립트의 데이터 타입 특징 때문에 생기는 문제

  • String, Number, Boolean 타입 데이터의 경우 변수에 값을 할당하면 값 자체가 저장된다.

  • 하지만 객체와 배열의 경우, 그 값 자체가 아닌 주소가 저장된다.

  • 두 객체가 같은 주소를 가리키고 있기 때문에, child2의 값을 변경하면 child1의 값도 동일하게 변경됨

  • 객체 복사라는 것은 존재하지 않는다.

  • 원본 객체와 같은 값을 가진 객체를 새로 만들 수 있을 뿐이다.

// child3에 child2 복사
let child3 = {
    name: child2.name,
    age: child2.age,
    school: child2.school
}

child3 // {name: '영희', age: 8, school: '다람쥐초등학교'}
// child3에 child2 복사
let child3 = {
    name: child2.name,
    age: child2.age,
    school: child2.school
}

child3 // {name: '영희', age: 8, school: '다람쥐초등학교'}

📂 스프레드 연산자

  • 객체를 복사할 때마다 원본 객체의 모든 값을 따로따로 가져오는 것은 번거로운 작업이다.

  • 객체에 들어가 있는 데이터의 양이 많아지면 실질적으로 불가능에 가까워 진다.

  • 그 때 사용할 수 있는 것이 스프레드 연산자

let child4 = {
	...child2
}

child4 // {name: '영희', age: 8, school: '다람쥐초등학교'}

📂 중첩 객체 복사 _ 스프레드 연산자

  • 스프레드 연산자 역시 객체 안에 객체가 값으로 들어가 있는 경우에는 제대로 복사가 되지 않는다.

  • 스프레드 연산자를 이용한 복사를 얕은 복사(Shallow-Copy)라고 한다.

  • 얕은 복사는 depth 1의 깊이를 가진 데이터까지는 복사할 수 있지만, depth 2 이상의 깊이를 가진 데이터는 복사하지 못한다.

📂 깊은 복사

  • JSON.stringifyJSON.parse라는 메소드를 이용하면 객체/배열을 문자열로, 그리고 문자열을 객체/배열로 바꾸어 줄 수 있다.

💡JSON

JavaScript Object Notation의 약자.
Javascript 객체 문법으로 구조화된 데이터를 표현하기 위한 문자 기반의 표준 포맷

JSON.stringify

JSON.stringify(profile1)
// '{"name":"철수","age":8,"school":"공룡초등학교","hobby":{"first":"수영","second":"프로그래밍"}}'

JSON.parse

JSON.parse(JSON.stringify(profile1))
// {name: '철수', age: 8, school: '공룡초등학교', hobby: {first: '수영', second: '프로그래밍'}}

✅ 댓글 수정하기


  • 글의 수정하기 버튼을 누르면, 다음과 같이 해당 댓글 영역만 수정하기 input으로 바뀐다.
import { gql, useQuery } from "@apollo/client";
import { useState } from "react";

const FETCH_BOARDS = gql`
  query fetchBoards($page: Int) {
    fetchBoards(page: $page) {
      _id
      writer
      title
    }
  }
`;

export default function PaginationPage() {
  const { data } = useQuery(FETCH_BOARDS, { variables: { page: 1 } });

	const [myIndex, setMyIndex] = useState([
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false,
  ]);

	const onClickEdit = (event: MouseEvent<HTMLButtonElement>): void => {
	  const temp = [...myIndex];
	  temp[Number(event.currentTarget.id)] = true;
	  setMyIndex(temp);
	};

  return (
		<div>
      {data?.fetchBoards.map((el, index) =>
        !myIndex[index] ? (
          <div key={el._id}>
            <span>{el.title}</span>
            <span>{el.writer}</span>
            <button onClick={onClickEdit} id={String(index)}>
              수정하기
            </button>
          </div>
        ) : (
          <input type="text" key={el._id}></input>
        )
      )}
    </div>
  );
}

✅ 무한스크롤


  • react infinite scroller
    import { useQuery, gql } from "@apollo/client";
    import type {
      IQuery,
      IQueryFetchBoardsArgs,
    } from "../../../src/commons/types/generated/types";
    import InfiniteScroll from "react-infinite-scroller";
    
    const FETCH_BOARDS = gql`
      query fetchBoards($page: Int) {
        fetchBoards(page: $page) {
          _id
          writer
          title
          contents
        }
      }
    `;
    
    export default function StaticRoutingMovedPage(): JSX.Element {
      const { data, fetchMore } = useQuery<
        Pick<IQuery, "fetchBoards">,
        IQueryFetchBoardsArgs
    (FETCH_BOARDS);
    
      const onLoadMore = (): void => {
        if (data === undefined) return;
    
        void fetchMore({
          variables: { page: Math.ceil((data?.fetchBoards.length ?? 10) / 10) + 1 },
          updateQuery: (prev, { fetchMoreResult }) => {
            if (fetchMoreResult.fetchBoards === undefined) {
              return {
                fetchBoards: [...prev.fetchBoards],
              };
            }
    
            return {
              fetchBoards: [...prev.fetchBoards, ...fetchMoreResult.fetchBoards],
            };
          },
        });
      };
    
      return (
        <div>
          <InfiniteScroll pageStart={0} loadMore={onLoadMore} hasMore={true}>
            {data?.fetchBoards.map((el) => (
              <div key={el._id}>
                <span style={{ margin: "10px" }}>{el.title}</span>
                <span style={{ margin: "10px" }}>{el.writer}</span>
              </div>
            )) ?? <div></div>}
          </InfiniteScroll>
        </div>
      );
    }
profile
개발 블로그

0개의 댓글