[React]Hooks : useEffect()함수 (feat. filter함수)

Suji Kang·2023년 9월 5일
0

use... 함수리액트 hook 함수

  • useState 함수 : state변수를 만들고싶을떄 사용(상태에 변화가있을경우)
    🌟 re-rendering 하고싶을때

🐾 useEffect()

useEffect (콜백함수 , 의존성배열);

📍 첫번째

useEffect( ()=>{ });

👇
콜백함수를 받음
컴포넌트가 랜더링될때마다 호출이 된다. 무거운 작업을 가지고 있다고하면, 매우 비효율적이기 때문에 이 방식은 거의 쓰지않음.

📍 두번쨰

useEffect( ()=>{ },[]);

👇
첫번째 랜더링만 호출

📝 만일 의존성 배열이 비어있는 배열이라면
앞에있는 함수는 🌟 최초 랜더링 될때만 실행이 된다

만일 의존성 배열(Dependency array)에 변수가 들어있다면
그변수가 변할때 마다 앞에있는 함수가 실행이 된다
👉👉 useEffect의 인자로 전달되는 함수 부분에 함수 return할수있다
이때 return 되는 함수는 cleanup 함수라고 한다

clean up-정리 예시

useEffect(() => {
	//구독...
     return()=> {
     //구독해지...
   }
},[]);

cleanup 함수unmount 되기전실행이 되는 함수를 의미한다

📌 useEffect 언제사용 ❓

특정 코드특정 상황에서만 실행이 되어야할떄,

✏️ 컴포넌트가 최초 로 그려질떄 한번만
✏️ 컴포넌트가 re-rendering 될때마다 실행
✏️ 컴포넌트가 사라질떄(unmount) 될떄 실행

useEffect.js

import React, { useEffect, useState } from 'react';

const UseEffectPage = () => {
const [cnt, setCnt] = useState(0);
const [msg, setMsg] = useState('기본값');

    console.log('hi')// 이코드는 언제 시작될까? => 해당 컴포넌트가 렌더링이 될때마다 실행됨

    useEffect(() => {
        console.log('의존성 배열이 없다면?')
    })

    useEffect(() => {
        console.log('useEffectPage가 최초 렌더링 될때만 실행됨')
    }, []);// 두번째 인자로 빈배열을 넣으면 최초 렌더링 될때만 실행됨


    useEffect(() => {
        console.log('cnt가 변경될때만 실행됨')
        return () => {
            console.log('cnt가 unmount 될때 실행됨 🌟 (기존컴포넌트가 사라질때')
        }
    }, [cnt]);// 두번째 인자로 cnt를 넣으면 cnt가 변경될때만 실행됨


    useEffect(() => {
        console.log('cnt 혹은 msg가 변경될때만 실행됨')
    }, [cnt, msg]);// 두번째 인자로 cnt를 넣으면 cnt가 변경될때만 실행됨


    useEffect(() => {
        return () => {
            console.log('unmount 될때 실행됨(기존컴포넌트가 사라질때')
        }
    }, []);// 두번째 인자로 빈배열을 넣으면 최초 렌더링 될때만 실행됨

  return (
    <>
      <h1>useEffectPage</h1>
      <h2>{count}</h2>
      <button onClick={() => setCnt(cnt - 1)}>-</button>
      <button onClick={() => setCnt(cnt + 1)}>+</button>
 	  <p>{msg}</p>
      <input type="text" onChange={(e) => setMsg(e.target.value)} />
    </>
   )
}

export default UseEffectPage;

useEffect에서 의존성 배열제공하지 않으면 해당 effect는 컴포넌트렌더링될 때마다 실행됩니다. 이로 인해 컴포넌트가 렌더링될 때마다 해당 코드 블록이 실행되며, 처음 렌더링 때부터 effect가 실행되어 콘솔에 메시지를 로깅합니다. 그 후에도 컴포넌트가 재렌더링될 때마다 같은 메시지가 반복적으로 로깅되며, 이로 인해 불필요한 작업이 발생할 수 있으므로 주의가 필요합니다.


또하나의 컴포넌트를 만들어줄거야 ❗️
Child.js

const Child = (props) => {
   useEffect(() => {
       //최초 렌더링 될때만 실행됨
       console.log('Child가 최초 렌더링 될때만 실행됨')
       console.log(props.componentTitle, '번째 자식이 만들어짐')

       //사라질때 실행됨 unmount 될때 실행됨(기존컴포넌트가 사라질때)
       return () => {
           console.log('props.componentTitle,번째 자식이 삭제')
           //부모의 state변수 cnt를 0으로 변경
           //setCnt
           props.setCnt(0);
           //부모의 state변수 msg를 'hi'로 변경
           //setMsg
           props.setMsg('hi');
       }
   }, []); // 두번째 인자로 빈배열을 넣으면 최초 렌더링 될때만 실행됨

   const onRemoveClick = (number) => {
       //number에는 뭐가 저장? => event객체가 저장됨
       console.log(number, '번째 자식이 삭제됨')
       // props.abc([1, 2])
       let res = props.arr.filter((e) => e !== number)
       props.abc(res);

   }

   // const wrapFuc = () => {
   //     onRemoveClick(props.componentTitle);
   // }

   return (
       <>
           <h1>{props.componentTitle}Child Component</h1>
           <button onClick={() =>
               onRemoveClick(props.componentTitle)
           }>Delete!</button>
           <button onClick={onRemoveClick}>Delete!</button>
       </>
   )
}

📝 useEffect component 에서 child component 로 가지고와서 사용하려고하는데 ❓props로 받아보자

useEffect.js

const useEffectPage = () => {
	const [cnt, setCnt] = useState(0);
	const [msg, setMsg] = useState('hi');
	const [arr, setArr] = useState([1, 2, 3]);

    return (
        <>
            {/* 
            <Child componentTitle={1}/>
            <Child componentTitle={2}/>
            <Child componentTitle={3}/> 
            이렇게 3개로 반복되니 배열로만들수있겠지? ( map 함수 사용가능 )
            */}
            {arr.map((e, index) => {
                return <Child componentTitle={e} key={index} arr={arr} setCnt={setCnt} setMsg={setMsg} abc={setArr} />
              }
            )} /* return하고 중괄호 생략가능 */
            <h1>useEffectPage</h1>
            <h2>{cnt}</h2>
            <button onClick={() => setCnt(cnt - 1)}>-</button>
            <button onClick={() => setCnt(cnt + 1)}>+</button>
            <p>{msg}</p>
            <input type="text" onChange={(e) => setMsg(e.target.value)} />
        </>
    )
}

export default useEffectPage;

부모에서 만든 함수를 자식에서 사용해야해서, 넘겨주려면 ? 🔎

부모에서 자식으로 을 전달해줘야된다. (props를 써서 넘겨줘야지)
component에 props로 arr setCnt setMsg setArr componentTitle 들을 넘겨줬기 때문에 넘겨준것들을 사용가능.

const Child = (props) => {
  //props를 받아준다
useEffect(() => {
  return () => {
           //부모의 state변수 cnt를 0으로 변경
           //setCnt
           props.setCnt(0);
           //부모의 state변수 msg를 'hi'로 변경
           //setMsg
           props.setMsg('hi');
       }
   }, []);

const onRemoveClick = (number) => {
  console.log(number);
  //이벤트정도를 객체로 넣어서 number로 받음 
 //props.abc([1,2]);
  props.abc(res);
}

 return (
       <>
           <h1>{props.componentTitle}Child Component</h1>
           <button onClick={() =>
			//onRemoveClick({이벤트정보}) 
			//이벤트정도를 객체로 담아서 전달 
 			onRemoveClick(props.componentTitle)
           }>Delete!</button>
           <button onClick={onRemoveClick}>Delete!</button>
       </>
   )
}

<Child arr={arr} setCnt={setCnt} setMsg={setMsg} abc={setArr} />
}


🐾 filter함수

📍 map

기존배열을 기반으로 새로운 배열을 만들어주는 함수

📍 filter

기존배열을 기반으로 걸러내어 새로운 배열을 만들어주는 함수

배열.filter( (요소, idx, arr)=>{ return true/false } )

기존 배열의 요소 갯수만큼 반복 하면서 true가 return 되는 요소만 모아서 새로운 배열을 만들어줌

arr = [10,50,61,50,71,231];
arr.filter( (e)=>{ return e > 50 } );
=> [61,71,231]

number = 1;
arr = [1,2,3]
let res = arr.filter( (e)=>{ return e !== number } );
//e가 1이 아닌것은?
=> [2,3]

🌟 fillter 사용할때 훼손하는지 안하는지 구분해야한다.

"filter 사용할 때 훼손하는지 안하는지 구분해야한다"는 배열을 다룰 때 중요한 개념 중 하나인데, 이것은 원본 배열을 변경하지 않는 것과 관련이 있다.

원본 배열을 훼손하지 않는 경우:
배열을 필터링하거나 수정할 때, 원본 배열을 그대로 두고 새로운 배열을 생성하는 방식이다. 이렇게 하면 원본 배열은 변경되지 않는다. 이것은 보통 함수형 프로그래밍에서 추천되는 방식이다.

예를 들어:

const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter(number => number % 2 === 0);

console.log(numbers);     // [1, 2, 3, 4, 5]
console.log(evenNumbers); // [2, 4]

원본 배열을 훼손하는 경우:
배열을 직접 수정하여 필터링 또는 변형하는 방식이다. 이 경우 원본 배열이 변경된다. 이것은 가끔 필요한 상황이지만, 주의해야 함.

예를 들어:

const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 !== 0) {
    numbers.splice(i, 1);
    i--; // 배열이 하나 삭제되었으므로 인덱스를 조정
  }
}

console.log(numbers); // [2, 4]

이 경우 splice 메서드를 사용하여 배열을 직접 수정하고 있으므로 numbers 배열이 변경됨.

원본 배열을 변경하지 않는 방식이 일반적으로 더 예측 가능하며 함수형 프로그래밍의 원칙에 부합하다. 따라서 배열을 필터링하거나 수정할 때 원본 배열을 훼손하지 않는 방식을 사용하는 것이 좋다.


예시:

const Test=()=>{
    console.log('hi')
    useEffect(()=>{
        console.log('welcome')
    });
    return(
        <div>
            <h1>Test</h1>
        </div>
    )
}
<Test/>
1. Test(); 
// hi 출력
// <Test/> 그려짐 mount 됨
// welcome 출력
Test 가 update 됨
기존 unmount 됨
새로 <Test/> re-rendering Test();
// hi 출력
// <Test/> 그려짐 mount 됨
// welcome 출력
profile
나를위한 노트필기 📒🔎📝

0개의 댓글