.filter, .map, .every, refetchQueries

huni_·2022년 7월 1일
0

지금까지 배운 것을 보면 반복문을 사용하기 위해서는 for문을 사용했습니다.

그런데 말야!!!

실무에서는 for문을 잘 사용하지 않는다는 점!!!!!!

그럼 뭘 써야 하냐?

오늘 배운 map을 사용합니다!!!

map과 filter 모두 배열의 내장함수이기 때문에 사용하실 때는 배열과 함께 사용해야 합니다.

1. map

map은 배열의 원소를 일괄적으로 변형시킬 때 사용하기 좋습니다.

1-1 . map의 사용방법

const classmate = ["철수","영희","훈이"]

classmate.map((item)=>(item+"어린이"))
=> (3)["철수어린이","영희어린이","훈이어린이"] 이렇게 됩니다.

classmate.map((el)=>(el+"어린이"))
=> (3)["철수어린이","영희어린이","훈이어린이"] 이렇게 됩니다.
// map() 소괄호 안에 넣은 파라미터랑 출력하고 싶은 부분에 파라미터가 같아야 합니다.
// map() 소괄호 안에 넣은 파라미터 === 엘리먼트 안에 있는 값

map안에서 사용되는 item은 classmate의 원소들이 들어갈 파라미터(매개변수) 입니다.
파라미터의 네이밍은 마음대로

객체가 원소인 배열에서도 map을 이용해 객체를 가공해보도록 하겠습니다.

const classmate = [
				{name: "철수"},
				{name: "영희"},
				{name: "훈이"}]

//item.name => "철수","영희","훈이"
//school 속성을 일괄적으로 추가해주도록 하겠습니다.
classmate.map((item)=>({name : item.name + "어린이", school : "떡잎유치원"}))
=> (3)[
{name : "철수어린이",school : "떡잎유치원"},
{name : "영희어린이",school : "떡잎유치원"},
{name : "훈이어린이",school : "떡잎유치원"}
]

💡 화살표 함수에서 소괄호를 생략이 가능할까요?
→ 정답은
상황에 따라 가능하다** 입니다.
본문(뒤의 괄호 안에 적히는 코드)이 한줄이라면 생략이 가능합니다.

그렇다면 언제 생략이 불가능 할까요?
리턴값이 객체인 경우생략이 불가능 합니다.
중괄호가 없어지면 객체의 중괄호가 함수의 중괄호가 되어버립니다.
따하서 리턴값이 객체일 경우엔 생략하시면 안됩니다.

💡 화살표 함수 () ⇒ {} vs () ⇒ ()
→ 소괄호 ()로 감싸진 부분이 return
됩니다.(return문을 작성하지 않아도 리턴 됩니다.)
반면 중괄호{}로 감싸진 함수는 return문이 없다면 리턴값을 반환하지 않습니다.

⇒ 화살표 함수



화살표 함수는 코드가 한 줄 일 경우 중괄호와 return 생략 가능합니다.

한 줄 이면 소괄호도 생략 가능합니다.

⭐ 소괄호 생략 가능한가?????

생략을 해버리는 순간 함수 {}(중괄호)가 됩니다.

실습


  • map 은 배열에서 실행이 가능합니다.
const clsssmates = ["철수","영희","훈이"]
undefined
clsssmates.map((el) => (el + "어린이"))
(3) ['철수어린이', '영희어린이', '훈이어린이']
const classmates2 = [
    {name: "철수"},
    {name: "영희"},
    {name: "훈이"}
]
classmates2.map((el)=>(el.name+"어린이"))
(3) ['철수어린이', '영희어린이', '훈이어린이']
const classmates2 = [
    {name: "철수"},
    {name: "영희"},
    {name: "훈이"}
]
classmates2.map((el)=>({name:el.name+"어린이"}))
(3) [{}, {}, {}]0: {name: '철수어린이'}1: {name: '영희어린이'}2: {name: '훈이어린이'}length: 3[[Prototype]]: Array(0)

함수명은 동사로 정하고 변수명은 명사로 정하는게 일반적이다.

return === “반환한다”라는 뜻도 있지만 함수를 “종료한다”라는 뜻도 있습니다.

2. filter

filter는 이름 그대로 배열의 원소를 필터링 해주는 메서드 입니다.

filter는 필터링 할 조건으로 객체 혹은 배열의 각원소를 검사하여 그 조건에 맞는 원소들만 결과값으로 도출해 줍니다.

2-1 . filter의 사용방법

const num = [1,2,3,4,5,6,7,8,9,10]

num.filter((item)=>(item<=8))
=> (8) [1, 2, 3, 4, 5, 6, 7, 8]

filter 안에서 사용되는 item 역시 배열의 원소가 들어갈 파라미터 입니다.

💡 map과 filter의 결과물 차이점
map은 배열의 길이만큼 값이 나오지만, filter는 조건에 따라 배열의 길이보다 적게 나옵니다.

fetchBoards === 배열로 저장되기 때문에 fetchBoards.number은 작동이 안됩니다.

number 값이 연결 됩니다.

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-![](https://velog.velcdn.com/images/rlaclgns321/post/6506cb71-3ad8-4420-8368-f9557a0cc3b7/image.png)

이벤트핸들러를 사용할 경우 반드시 파라미터로 이벤트를 삽입해주어야 합니다.

event값 연결 시켜서 id 값을 연결 시킵니다.

<></> 이 fragment는 key를 입력할 수 없습니다.

이 fragment 는 key로 입력 가능합니다.

React에서 Key가 필요한 이유

해당 경고는 React가 어떤 요소를 변경, 추가, 삭제할지 식별하기 위함입니다. key가 없는 경우에는 가상 DOM을 비교하는 과정에서 순차적으로 비교하며 변화를 감지합니다. key가 있다면, 이 값을 사용하여 어떤 것이 수정이 됐는지 빠르게 감지할 수 있습니다.

(이 부분은 react가 브라우저에 그려지는 과정, 가상 DOM에 대해 공부하시면 더 빠르게 이해하실 수 있습니다.)

위의 설명을 짧게 보충한다면, React에서는 기존 데이터와 바뀐 데이터를 비교하여 바뀐 부분을 화면에 그려줍니다.

여기서 비교할 때 고유한 Key값이 없다면 모든 데이터를 비교해야 하지만, Key가 있으면 Key값만 비교하여 Key가 추가 됐는지, 삭제 됐는지만 비교하여 불필요한 비교나 렌더링을 없애줍니다.

그러기 위해 key는 안정적인 고유성을 부여하기 위해 중복되는 값이 아닌 것으로 지정해줘야 합니다. (만약 key를 지정하지 않을 경우 자동으로 index를 키로 사용합니다. 하지만 이는 좋은 방법이 아니라 경고가 뜹니다.)

그래서 React 공식 문서에서도 Key 값으로 id를 주는 것을 추천합니다.

(아래는 예제이기 때문에 id가 없지만 예시로 넣어두었습니다.)

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

export default function Test2() {
	const List = ['사과', '딸기', '바나나'];

	return (
		<>
			{List.map((data) => (
				<Test key={id}>{data}</Test>
			))}
		</>
	);
}

앞으로 여러분의 효율적인 React를 위해 map을 쓰실 때는 꼭 id값을 적어주세요.

Index를 Key로 줘도 괜찮은 상황

index를 key로 줘도 괜찮은 상황이 있습니다. 아래 3가지 조건을 만족하면 됩니다.

  1. 정적인 데이터. 계산되지 않고 변경되지 않는 데이터
  2. map에 있는 모든 데이터에 id가 없을 경우
  3. 데이터가 재정렬되거나 필터링 되지 않는 경우. (계속 그 자리 그대로)

위의 3가지를 만족한다면 index를 key로 사용해도 안전합니다.

하지만 서버에서 받아오는 데이터라면 그럴리 없겠죠?

index와 key에 대한 설명 링크


refetchQueries

refetchQuery는 기존에 받아왔던 데이터가 변경 되었을 경우 최신 데이터로 다시 fetch 해주기 위해 사용됩니다.

어떻게 사용하는지 예제를 통해 알아보겠습니다. 아래 예제는 사용 방법으로만 보시면 좋을 것 같습니다.

refetchQuery 의 사용 방법

// 삭제 Mutation

const deleteBoard = async () => {
	try {
		const result = await deleteBoard({
			variables: {
				boardId: router.query.boardId,
			},
		});
	} catch (error) {
		console.log(error);
	}
};

위의 코드는 흔하게 볼 수 있는 삭제 Mutation입니다.

위 코드는 삭제 Mutation이 실행 된 후에는 데이터가 변경 되었을 테지만 아직 최신 데이터가 반영 되지 않았습니다.

따라서 refetchQueries를 이용해 최신 데이터로 다시 받아오겠습니다.

//refetchQueries를 이용해 최신 데이터 받아오기

const deleteBoard = async () => {
	try {
		const result = await deleteBoard({
			variables: {
				boardId: router.query.boardId,
			},
			refetchQueries: [
				{
					query: FETCH_BOARDS
				},
			]
		});
	} catch (error) {
		console.log(error);
	}
};

위의 코드를 자세히 살펴보시면 useMutation 함수 안에서 refetchQueries라는 키가 있다는 것을 알 수 있습니다. refetchQueries는 Apollo에서 제공하는 기본 기능입니다.

refetchQueries는 배열로 시작하여, 그 안에 어떤 query를 하고, 그 query의 variables가 무엇인지 다시 설정해주면 Mutation이 성공적으로 끝났을 경우 refetchQueries를 실행시켜줍니다.

💡 refetchQueries에서의 variables
→ 기존의 fetch 부분에서 보내준 variables가 없다면 따로 적지 않아도 되지만, 만일 보내준 variables가 있다면 refetchQuerise부분을 아래와 같이 적어주세요

refetchQueries: [{ query : FETCH_BOARDS, variables : { 기존의 fetch때 보내준 것 } }]

(모든 Mutation 이후에 refetchQueries를 사용하는 것은 아닙니다. Mutation 이후 변경된 데이터를 받아올 수 없을 경우에 사용합니다.)


map의 index를 key로 사용시 발생하는 문제점

react 공식 문서에 나오는 key와 id 링크

여기까지 오신 분들은 아마 map을 통해서 데이터를 한 번에 뿌리는 것 까지 오셨을 겁니다.

그런데 map을 하면 한 가지 문제점이 발생합니다.

간단한 예제를 보겠습니다.

리스트를 map을 통해 한 번에 보여주고 있습니다.

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

export default function Test2() {
	const List = ['사과', '딸기', '바나나'];

	return (
		<>
			{List.map((data) => (
				<Test>{data}</Test>
			))}
		</>
	);
}

그런데 말입니다.

console.log()가 이상합니다.

오류 메시지를 해석해보겠습니다.

음.. 각각의 child은 unique한 "key"가 있어야 한다는 것 같네요.

왜 이런 메시지가 뜨는 것일까요?

key가 없어 오류가 나옵니다.

그러기 때문에 key값을 부여하면 해결!!!

every

every

배열 안의 모든 원소가 주어진 판별함수를 통과하는지 테스트하며, Boolean을 반환합니다.

some과 비슷하지만 모든 원소가 만족해야 한다는 점에서 차이가 있습니다.

/* every의 사용방법 */
const 콜백함수 = (arr_item)=>{//판별하고싶은 것}

arr.every(//콜백함수)

arr_item에는 arr의 모든 원소가 들어가게 됩니다.

아래에서 예제를 통해 조금 더 자세히 보도록 하겠습니다.

// every의 예제
const array = [2,4,6,8]
const elFunc = (item)=>{return item%2===o}

console.log(array.every(elFunc))

> 결과 <
true
const isBelowThreshold = (currentValue) => currentValue < 40;

const array1 = [1, 30, 39, 29, 10, 13];

console.log(array1.every(isBelowThreshold));
// expected output: true
// 화살표 함수
every((element) => { ... } )
every((element, index) => { ... } )
every((element, index, array) => { ... } )

// 콜백 함수
every(callbackFn)
every(callbackFn, thisArg)

// 인라인 콜백 함수
every(function callbackFn(element) { ... })
every(function callbackFn(element, index) { ... })
every(function callbackFn(element, index, array){ ... })
every(function callbackFn(element, index, array) { ... }, thisArg)
profile
FrontEnd Developer

0개의 댓글