[React] Props,State,Event,Hook 정리

김보나·2021년 10월 11일
4

React

목록 보기
3/15
post-thumbnail

Props(properties)

  • 컴포넌트에 원하는 값 을 넘겨줄 때 사용.
  • 변수,함수,객체,배열 등 자바스크립트의 요소라면 제한이 없음
  • 컴포넌트의 재사용을 위하여 사용함.
  • 읽기 전용임 → 값 변경 불가
  • 값을 변경하고 싶으면 새로운 변수를 생성해서 사용해야함.
  • 임의로 재할당하여 사용시 렌더링할때 문제가 발생함.

활용 예시

  1. props를 활용한 컴포넌트 만들기

    • Info 태그를 사용할 때 지정한 이름을 props.지정한이름 으로 받아주면 된다.
      //App.js
      import Info from "./Info";
      import "./App.css";
      
      function App() {
        return (
          <div className="App">
            <Info memberName="박시은" />
          </div>
        );
      }
      
      export default App;
      
      //Info.js
      import React from "react";
      
      function Info(props) {
        const memberName = props.memberName;
        return <h1>멤버 이름은 {memberName}입니다.</h1>;
      }
      
      export default Info;
    • 결과
  2. 객체 props 받고 연산하기

    • props에 이름을 붙여 넘겨주기
    • object를 넘겨주면 . 을 통해 object의 속성에 접근하여 값을 불러올 수 있음.
    //Member.js
    
    import React from "react";
    
    function Member({ member }) {
      let isAdult = member.age >= 20 ? "성인" : "미성년자";
    
      return (
        <>
          <p>
            멤버의 이름은 {member.name}이고 현재 {isAdult} 입니다.멤버의 이름은 {member.name}이고 포지션은 {member.role}이며, 현재{" "}
            {isAdult} 입니다.
          </p>
        </>
      );
    }
    
    export default Member;
    
    //App.js
    import Info from "./Info";
    import "./App.css";
    import Member from "./Member";
    
    function App() {
      const member1 = {
        name: "박시은",
        age: "21",
        role: "메인 보컬",
      };
      const member2 = {
        name: "김채영",
        age: "20",
        role: "리드 보컬",
      };
      const member3 = {
        name: "장재이",
        age: "17",
        role: "서브 보컬",
      };
    
      return (
        <div className="App">
          {/* <Info memberName="박시은" /> */}
          <Member member={member1} />
          <Member member={member2} />
          <Member member={member3} />
        </div>
      );
    }
    
    export default App;
    • 결과

State

  • 컴포넌트에서 유동적으로 변할 수 있는 값을 저장합니다.
  • state에서 값이 변경되어 재 랜더링이 필요할 경우에는 리액트가 자동으로 감지하여 변경된 부분을 렌더링합니다.
  • hook 선언은 꼭 최상단 컴포넌트 안에 합니다.

사용 방법

  1. state의 값은 절대 직접 변경하지 않고 setState를 이용하여 변경합니다.
  2. setState에 변경할 값을 넣거나
  3. setState에 함수를 넣어 state를 변경합니다.

⇒ 현재 값을 기반으로 state를 변경할 때는 함수로 변경하는 것이 권장된다고합니다.

예제

  1. state를 사용하여 클릭할 때 마다 값 변경하기
    • button안의 onClick 함수에서 current를 이용해서 함수로 setMember를 변경했음!
    • 객체를 변경할때는 기존객체의 데이터에 손을 대지말고, 객체를 복사해서 써야함!
    • 코드
      //App.js
      
      import Info from "./Info";
      import "./App.css";
      import Member from "./Member";
      import { FcLike } from "react-icons/fc";
      import React, { useState } from "react";
      
      function App() {
        const [member, setMember] = useState({
          name: "박시은",
          age: "21",
          role: "메인 보컬",
          like: 0,
        });
        
        return (
          <div className="App">
             <Member member={member} />
            <button
              onClick={() => {
      
                setMember((current) => {
                  const newMember = { ...current };
                  newMember.like = current.like + 1;
                  return newMember;
                });
              }}
            >
              <FcLike />
            </button>
          </div>
        );
      }
      
      export default App;
      
      //Member.js
      import React, { useState } from "react";
      import { FcLike } from "react-icons/fc";
      
      function Member({ member }) {
        let isAdult = member.age >= 20 ? "성인" : "미성년자";
      
        return (
          <>
            <p>
              멤버의 이름은 {member.name}이고 포지션은 {member.role}이며, 현재
              {isAdult} 입니다.
              <br />
              하트 수 <FcLike /> {member.like}
            </p>
          </>
        );
      }
      
      export default Member;
    • 결과
    1. 텍스트 필드가 변경될 때 마다 바뀌는 state
      • input 태그의 onChange 속성에 이벤트를 매개변수로 받는 익명함수를 선언
      • 내용이 바뀔 때마다 setMessage를 통하여 값을 바꾸게 함!
      • onChange 함수는 변화가 있을 때마다 할당된 일을 수행함
      • 코드
        //App.js
        
        import React, { useState } from "react";
        
        function App() {
        
          const [message, setMessage] = useState();
        
          return (
            <div className="App">
              <h3>{message}</h3>
              <input
                value={message}
                onChange={(ev) => {
                  setMessage(ev.target.value);
                }}
              ></input>
            </div>
          );
        }
        
        export default App;
      • 결과

Event

  • 웹 브라우저가 알려주는 html 요소에 대한 사건을 의미합니다.
  • 유저 행동이나 개발자가 의도한 로직에 의해 발생됩니다.
  • 이벤트 핸들러 함수 : 이벤트를 처리하는 함수로, 로직을 처리하고 결과를 사용자에게 알립니다.
  • 핸들링 방법
    1. 별도로 함수를 선언하고 element로 넘겨주기
    2. 이벤트를 할당하는 부분에 익명함수 작성
  • 이벤트 객체
    • 이벤트 object를 이용하여 이벤트 발생 원인 및 이벤트가 일어난 element에 대한 정보를 얻을 수 있습니다.
    • 이벤트에 따라 전달되는 object의 내용이 다르니 구글링을 통해 알아보고 사용하면 좋습니다.
  • 많이 사용하는 이벤트
    • onClick
    • onChange
    • onKeyDown,onKeyUp,onKeyPress : 키보드 입력이 일어났을때
    • onDoubleClick
    • onFocus
    • onBlur :element가 포커스를 잃었을때
    • onSubmit : Form 에서 submit 했을 때

예제

  1. 핸들링 함수를 선언하여 이벤트 처리하기

    • isImgOn과 같은 bool타입 변수를 바꿔줄때도 setState를 이용하여 변화를 줘야함!
    • isImgOnlet 으로 선언해서 값 변경을 해도 리액트는 변화를 감지하지 못함!
    • 코드
      import Info from "./Info";
      import "./App.css";
      import Member from "./Member";
      import { FcLike } from "react-icons/fc";
      import React, { useState } from "react";
      
      function App() {
        const [isImgOn, setImgOn] = useState(false);
        const handleImg = () => {
          setImgOn(!isImgOn);
        };
        const sImg =
          "http://www.stardailynews.co.kr/news/photo/202109/308471_354191_1158.jpg";
        return (
          <div className="App">
            <button onClick={handleImg}>사진</button>
            <div>{isImgOn ? <img alt="시은" src={sImg} /> : ""}</div>
          </div>
        );
      }
      
      export default App;
    • 결과
    1. 한 개의 이벤트 핸들러를 여러 element에 재사용하기
      • 잊지말자 객체의 값을 변경할 때는 current를 이용하여 복사하는 것을
      • name 에 객체 속성 값을 넣어줘서 값을 변경함
      • value 에는 기본 값이 들어있다.
      • 코드
        
        import React, { useState } from "react";
        
        function App() {
        
         const [fan, setFan] = useState({
            name: "김릴리",
            song: "Slow Down",
          });
        
          const handleChange = (ev) => {
            const { name, value } = ev.target;
            setFan((current) => {
              const newFan = { ...current };
              newFan[name] = value;
              return newFan;
            });
          };
        
          return (
            <div className="App">
              <input type="text" name="name" value={fan.name} onChange={handleChange} />
              <input type="text" name="song" value={fan.song} onChange={handleChange} />
              <button
                onClick={() => {
                  alert(`${fan.name}의 최애곡은 ${fan.song}입니다.`);
                }}
              >
                확인
              </button>
            </div>
          );
        }
        
        export default App;
      • 결과
    2. 다른 컴포넌트로 이벤트 전달하기
      • 컴포넌트의 매개변수로 이벤트 함수를 전달받으면 된다.
      • 코드
        //UserForm.js
        import React from "react";
        
        function UserForm({ onChange }) {
          return <input onChange={onChange} />;
        }
        
        export default UserForm;
        
        //App.js
        import UserForm from "./UserForm";
        
        function App() {
          
          const [username, setUserName] = useState("아무개");
        
          return (
            <div className="App">
              <h1>{username}의 블로그</h1>
              <UserForm
                onChange={(ev) => {
                  setUserName(ev.target.value);
                }}
              />
            </div>
          );
        }
        
        export default App;
      • 결과


Hooks

  • 컴포넌트에서 데이터를 관리하고 데이터가 변경될 때 상호작용을 하기 위해 사용함
  • hook의 이름은 use로 시작하며 개발자가 직접 커스텀해서 사용할 수 도 있음.
  • 주의사항
    1. 리액트 함수(컴포넌트, 훅) 내에서만 사용가능함.
    2. 이름은 반드시 use로 시작해야함.
    3. 최상위 level에서만 훅 호출 가능 → for,if문 안쪽이나 콜백함수에서 호출 불가

hook의 종류

  1. useState : 컴포넌트 내 동적인 데이터 관리

    • 기본형
      const App=()=>{
      const[state이름, setState이름] = useState(초기값);
      	}
    • 최초 호출될때 초기값으로 설정되고 이 후 재렌더링 될때는 무시됨.
    • state가 변경되면 자동으로 컴포넌트가 재 렌더링됨.
    • 사용 예시는 위의 예제에서 전부 useState를 사용했으므로 생략
  2. useEffect : state의 값이 변경될 때 마다 설정해 놓은 함수가 호출됨.

    • 컴포넌트가 생성될 때, 소멸될 때를 감지하여 특정 로직을 실행할 수 있음.

    • 기본형

      • Deps -> 변경을 감지할 변수들의 집합(배열)

      • EffectCallback : Deps에 지정된 변수가 변경될 때 실행할 함수

        
        const App=()=>{
        	useEffect(EffectCallback, Deps?)	
        
        }
        
    • 예제 - 값 변경시 감지

      • username의 값이 변경될때 마다 콘솔로그에 username이 찍힘

      • event의 3번 예제 응용

        //UserForm.js
        import React from "react";
        
        function UserForm({ onChange }) {
          return <input onChange={onChange} />;
        }
        
        export default UserForm;
        
        //App.js
        import UserForm from "./UserForm";
        
        function App() {
          
          const [username, setUserName] = useState("아무개");
        
        	useEffect(() => {
            console.log(username);
          }, [username]);
        
          return (
            <div className="App">
              <h1>{username}의 블로그</h1>
              <UserForm
                onChange={(ev) => {
                  setUserName(ev.target.value);
                }}
              />
            </div>
          );
        }
        
        export default App;
      • 결과

        1. 화면
        2. 콘솔창
    • 예제 2 - 컴포넌트의 생성/소멸 확인

      • {isImgOn && <Info />} : isImgOntrue일 경우 Info 출력
      • 코드
        //Info.js
        import React, { useEffect } from "react";
        
        function Info(props) {
          useEffect(() => {
            console.log("컴포넌트 생성");
            return () => {
              console.log("컴포넌트 소멸");
            };
          }, []);
        
          return null;
        }
        
        export default Info;
        
        //App.js
        import Info from "./Info";
        import "./App.css";
        import React, { useState, useEffect } from "react";
        
        function App() {
           const [isImgOn, setImgOn] = useState(false);
          const handleImg = () => {
            setImgOn(!isImgOn);
          };
          const sImg =
            "http://www.stardailynews.co.kr/news/photo/202109/308471_354191_1158.jpg";
        
          return (
            <div className="App">
              
              <button onClick={handleImg}>사진</button>
              <div>{isImgOn ? <img alt="시은" src={sImg} /> : ""}</div>
                    {isImgOn && <Info />}
            </div>
          );
        }
        
        export default App;
      • 결과
        1. 화면

        2. 콘솔

    1. useMemo
      • 메모제이션이란? 메모제이션 :컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다. 동적 계획법의 핵심이 되는 기술이다
      • 지정한 state나 prop가 변경될 경우 해당 값을 활용해 계산된 값을
        메모이제이션하여 재 렌더링시 불필요한 연산을 줄임.
      • 랜더링 단계에서 연산을 하므로 시간이 오래걸리는 로직은 작성하지 않는게 좋음.
      • 성능 연산에 영향을 끼치니 유의할것~!
      • 모든 자바스크립트 연산결과를 메모이제이션함.
      • 예제
        • 다른 hook으로 구현했을 때 보다 연산이 빨라짐!
        • 코드
          import React, { useState, useEffect, useMemo } from "react";
          
          function App() {
            
            const [num1, setNum1] = useState(0);
            const [num2, setNum2] = useState(0);
            const multi = useMemo(() => {
              return num1 * num2;
            }, [num1, num2]);
          
            return (
              <div className="App">
                 <input
                  value={num1}
                  onChange={(event) => {
                    setNum1(parseInt(event.target.value));
                  }}
                />
          
                <input
                  value={num2}
                  onChange={(event) => {
                    setNum2(parseInt(event.target.value));
                  }}
                />
                <div>
                  {num1}*{num2}={multi}
                </div>
              </div>
            );
          }
          
          export default App;
        • 결과
      1. useCallback
        - 함수를 메모제이션 하기 위해 사용하는 hook.
        - 컴포넌트가 재 렌더링 될때 불필요하게 함수가 다시 생성되는 것을 방지함.
        - useMemo(()⇒fn,deps)useCallback(fn,deps)는 같음
        - usememo에서 함수를 리턴하는 것과 usecallback에서 함수를 넣어주는것은 같음.
        - 예제
        - useCallback은 함수형태로 사용해야함!
           ```jsx
             
             import React, { useState, useEffect, useMemo, useCallback } from "react";
             
             function App() {
               
               const [num1, setNum1] = useState(0);
               const [num2, setNum2] = useState(0);
               const multi = useMemo(() => {
                 return num1 * num2;
               }, [num1, num2]);
             const calc = useCallback(() => {
                 return num1 + num2;
               }, [num1, num2]);
             
               return (
                 <div className="App">
                    <input
                     value={num1}
                     onChange={(event) => {
                       setNum1(parseInt(event.target.value));
                     }}
                   />
             
                   <input
                     value={num2}
                     onChange={(event) => {
                       setNum2(parseInt(event.target.value));
                     }}
                   />
                   <div>
                     {num1}*{num2}={multi}
                   </div>
             			<div>
                     {num1}+{num2}={calc()}
                   </div>
                 </div>
               );
             }
             
             export default App;
             
             ```
             
        • 결과
      2. useRef
        • 컴포넌트 생애 주기 내에서 유지할 ref 객체를 반환함.
        • ref 객체는 .current라는 프로퍼티를 가지며 값을 자유롭게 변경할 수 있음.
        • 일반적으로 DOM element에 접근할때 사용함.→ DOM element의 ref속성을 이용.
        • useRef에 의해 반환된 ref 객체가 변경되어도 컴포넌트가 재렌더링 되지 않음.
        • 실습
          import React,{useRef} from 'react';
          
          function App() {
              const inputRef = useRef();
              
            return (
              <div className="App">
              <input ref={inputRef} />
              <button onClick={()=>{
              alert(inputRef.current.value);
              }}>
              클릭
              </button>
              </div>
            );
          }
          
          export default App;
        • 결과
           
    2. hook 만들기
      - 컴포넌트 로직을 함수로 뽑아내어 재사용 가능
      - 로직의 재사용을 높이기 위해서는 custom hook 제작
      - hook 이름은 use로 시작하기
      - 하나의 hook 안의 state는 공유되지 않음!
      - 실습
      - 토글 hook 만들기
         ```jsx
               //useToggle.js
               import React,{useState} from 'react';
               
               const useToggle =(initialValue)=>{
                   const [isOn, setIsOn] = useState(initialValue);
                   const toggle=()=>{
                       setIsOn((current)=>{
                       return !current;
                       });
                   }
                   
                   return {isOn, toggle};
               
               }
               
               export default useToggle;
               
               //App.js
               import React from 'react';
               import useToggle from './hooks/useToggle';
               
               function App() {
                   const{isOn, toggle} = useToggle(false);
                 return (
                   <div className="App">
                   <button onClick={()=>{
                       toggle();
                   }}>
                   {isOn ? "켜짐" : "꺼짐"}
                   </button>
                   </div>
                 );
               }
               
               export default App;
               ```
profile
우주최강 개발자가 될 때까지😈

1개의 댓글