Optional-Chaining 비구조화할당 폴더구조 Props refetchQueries 재사용성

hyeseon han·2021년 9월 27일
0

Optional-Chaining

기존의 && 연산자를 쓰면서 길어졌던 코드를 더욱 간결하게 사용하는 연산자.
연산자 앞 객체의 참조가 undefined || null 이라면 undefined를 리턴한다.

data?.fetchProfile

조건부렌더링

삼항 연사자

data는 동기적으로 받아와야한다. 하지만 데이터가 오기 전에 이미 return 부분에서 rendering을 해주고 있기 때문에 삼항 연산자를 써서 데이터가 있을 때, 없을 때를 모두 적어줘야한다.

data ? data.fetchProfile : undefined

&& 연산자

&& 연산자는 데이터가 없을 경우 자동으로 undefined를 반환해준다. 데이터가 없을 때 따로 div를 쓸 필요가 없으면 else부분을 쓸 필요가 없다.

data && data.fetchProfile

nullish-coalescing

?? 연산자: 좌측 피연산자가 nullish (null or undefined) 일 때 우측 피연산자를 반환
|| 연산자: 좌측 피연산자가 falsy (null, undefined, '', 0)일 경우 우측 피연산자를 반환
data ?? data.fetchProfile
// null이거나 undefined일 때 data.fetchProfile 그린다

data || data.fetchProfile
// 앞 부분이 거짓이면 뒷 부분을 그린다.

거짓

0
""
false
null
undefined

비구조화할당(=구조분해)

배열과 객체를 해체하여 안의 값을 사용하는 것이다. 말 그대로 배열, 객체의 구조를 분해하고 할당한다.

배열 구조 분해

// 배열 예
let data = ["one", "two", "three"];

구조 분해할당을 통해 데이터를 다시 담는다.

[,,] = data;
console.log() // "one"
console.log() // "two"
console.log() // "three"

const [a, b] = [1, 2]
console.log(a) // 1
console.log(b) // 2

useState와 동일한 형태이다.

const [count, setCount] = useState(0)

const count = useState(0)[0]
const setCount = useState(0)[1]

객체 구조 분해

// 객체 예
let profile = {name:"철수", age:8}

객체에서 값을 꺼낼 때 객체의 키로 접근

const {name, age} = profile
console.log(name) // "철수"
console.log(age) // 8

const {name:aaa, age:bbb} = profile
console.log(aaa) // "철수"
console.log(bbb) // 8

만약 구조 분해 할당을 안 하면

const {data} = useQuery(블라블라블라)

data.data.fetchBoard 로 받아야한다. 구조 분해 할당을 통해 data.fetchBoard 이렇게 사용이 가능하다.


폴더구조

container / presenter 패턴

container: 자바스크립트(기능) 부분 의미
presenter: HTML(UI) 부분 의미

props

Props값을 전달할 때, Container → Presenter 단방향만 가능(자식 → 부모 불가능 )

컴포넌트를 2개로 나누면 부모컴포넌트와 자식컴포넌트를 props로 연결할 수 있다.

emotion에 props

import { useState } from 'react';
import { Test } from '../../src/test2';

export default function Test2() {
	const [isTrue, setIsTrue] = useState(false);

	const handleOnClick = () => {
		setIsTrue((prev) => !prev);
	};

	return (
		return (
		<>
        	// isTrue 값을 넘긴다.
			<Test isTrue={isTrue} onClick={handleOnClick}>클릭하면 색이 왔다 갔다</Test>
		</>
		);
	);
}

container에서 presenter로 props를 넘기는 방식과 동일하다. emotion에 props를 넘기면 된다.

import styled from '@emotion/styled';

export const Test = styled.div`
	color: ${(props) => (props.isTrue ? 'red' : 'blue')};
`

event.target.value
값을 써주면 실시간으로 바뀌는 값을 적용할 수 있음.


refetchQueries

Query를 다시 Fetch한다.
useMutation을 한 후 기존에 받아왔던 Query의 Data가 변경되었을 경우 사용한다.

export default function MapSelectorPage(){
    const [deleteBoard] = useMutation(DELETE_BOARD)
    const { data } = useQuery(FETCH_BOARDS)

    async function onClickDelete(event){
        await deleteBoard({
            variables: {number: Number(event.target.id)},
            refetchQueries: [{query: FETCH_BOARDS}]
         })
    }

    return (
        <div>
            {data?.fetchBoards.map((el, index) =>(
                <Row key={el.nu}>
                    <Column>
                        <input type="checkbox"/>
                    </Column> 
                    <Column>{index}</Column> 
                    <Column>{el.title}</Column>
                    <Column>{el.writer}</Column>
                    <Column>{el.createdAt}</Column>
                    <Column>
                        <button id={el.number} onClick={onClickDelete}>삭제하기</button>
                    </Column>
                </Row>
            ))} 
        </div>
    )
}
  • useMutation 함수 안에서 refetchQueries가 있다.(Apollo에서 제공하는 기본 기능)
  • refetchQueries는 배열로 시작하여, 그 안에 어떤 query를 하고, 그 query의 variables가 무엇인지 다시 설정해주면 Mutation이 성공적으로 끝났을 경우 refetchQueries를 실행.
  • onClickDelete가 실행이 되면 Query의 Data가 변경되는데, 변경된 값이 apollo cache state라는 임시 저장소에 저장이 되고 이 값을 refetchQueries가 전달한다. 그래서 새로고침을 하지 않아도 새로고침한 것 같다.

컴포넌트 재사용성

import { MyButton, Title } from "./BoardWrite.styles"

export default function BoardWriteUI(props){
    return (
        <>
            <h1>{props.isEdit ? "수정페이지" : "등록페이지"}</h1>
            <Title zzz={props.zzz}>컨테이너 프리젠터 패턴!!!</Title>
            작성자: <input type="text" onChange={props.onChangeMyWriter} defaultValue={props.data?.fetchBoard.writer} /><br />
            제목: <input type="text" onChange={props.onChangeMyTitle} defaultValue={props.data?.fetchBoard.title} /><br />
            내용: <input type="text" onChange={props.onChangeMyContents} defaultValue={props.data?.fetchBoard.contents} /><br />
            {!props.isEdit &&<MyButton onClick={props.aaa} qqq={props.qqq}>등록하기</MyButton>}
            {props.isEdit &&<MyButton onClick={props.onClickEdit} qqq={props.qqq}>수정하기</MyButton>}
        </>
    )
}

package.json

"scripts" : 실행하는 명령어. Ex) dev
"dependencies" : yarn dev 했을 때 실행되는 것. 실행할 때 필요한 프로그램
"devDependencies" : 실행할 때 필요는 없지만 실행하기 전에 html, css 변경하기 전까지 임시로 사용. 개발할 때 필요. ex: TypeScript

0개의 댓글