기존의 && 연산자를 쓰면서 길어졌던 코드를 더욱 간결하게 사용하는 연산자.
연산자 앞 객체의 참조가 undefined || null 이라면 undefined를 리턴한다.
data?.fetchProfile
data는 동기적으로 받아와야한다. 하지만 데이터가 오기 전에 이미 return
부분에서 rendering을 해주고 있기 때문에 삼항 연산자를 써서 데이터가 있을 때, 없을 때를 모두 적어줘야한다.
data ? data.fetchProfile : undefined
&& 연산자는 데이터가 없을 경우 자동으로 undefined
를 반환해준다. 데이터가 없을 때 따로 div
를 쓸 필요가 없으면 else
부분을 쓸 필요가 없다.
data && data.fetchProfile
?? 연산자: 좌측 피연산자가 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: HTML(UI) 부분 의미
Props값을 전달할 때, Container → Presenter 단방향만 가능(자식 → 부모 불가능 )
컴포넌트를 2개로 나누면 부모컴포넌트와 자식컴포넌트를 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
값을 써주면 실시간으로 바뀌는 값을 적용할 수 있음.
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>
)
}
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