ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [포스코x코딩온] React-Event Handling, 합성 이벤트, state, setState, useState, Hook
    [포스코x코딩온] 웹개발자 풀스택 부트캠프8기 2023. 9. 21. 22:44
    728x90

    React

    Event Handling

    https://ko.legacy.reactjs.org/docs/handling-events.html

     

    이벤트 처리하기 – React

    A JavaScript library for building user interfaces

    ko.legacy.reactjs.org

    React의 Event

    • HTML Event
    <button onClick="buttonEvent();">
    	Event Button
    </button>
    • React Event
    <button onClick={buttonEvent}>
    	Event Button
    </button>
    
    //인라인 방식으로도 정의 가능
    <button onClick={()=> alert("클릭되었습니다")}>
    </button>
    • 위 두 개의 차이점을 아시겠나요?
      • React Event에는 ()가 없다. 
        • () 끝부분에서 클릭 없이 렌더링하는 동안 즉시 함수를 실행하기 때문에 사용하면 안 된다.
    • 인라인 방식으로도 정의할 수 있는데 이때, 화살표 함수를 꼭 사용해야 한다.

    React의 Event 주의점

    • React의 이벤트는 소문자 대신 카멜 케이스(camelCase)를 사용한다.
    • JSX를 사용해 이벤트 핸들러를 전달한다.
    • 기본DOM 요소에만 이벤트 설정이 가능하다.
      • 직접 만든 컴포넌트에 이벤트 자체 설정 불가능

    React합성 이벤트

     

    합성 이벤트(SyntheticEvent) – React

    A JavaScript library for building user interfaces

    ko.legacy.reactjs.org


    함수에 인자 보내기

    • 화살표 함수 이용하기
    <button onClick={() => onClickEvent("인자1")}>클릭 이벤트</button>
    <button onClick={(e) => onClickEvent2(e, "인자1")}>클릭 이벤트</button>
    • e : "이벤트"를 의미하여 이 개체를 사용하여 이벤트에 대한 정보를 읽을 수 있다.

    e 개체를 사용하여 전파 중지하기

    • e.stopPopagation()
      • 이벤트가 상위 구성 요소에 도달하는 것을 방지하려면 e.stopPopagation()을 호출하면 된다.
        • 아래의 경우 버튼을 클릭했을 때 e.stopPopagation()을 호출하여 두 개의 버튼이 눌리는 것을 방지한다.
    function Button({ onClick, children }) {
      return (
        <button onClick={e => {
          e.stopPropagation();
          onClick();
        }}>
          {children}
        </button>
      );
    }
    
    export default function Toolbar() {
      return (
        <div className="Toolbar" onClick={() => {
          alert('You clicked on the toolbar!');
        }}>
          <Button onClick={() => alert('Playing!')}>
            Play Movie
          </Button>
          <Button onClick={() => alert('Uploading!')}>
            Upload Image
          </Button>
        </div>
      );
    }
    • e.preventDefault()
      • 몇 가지 이벤트에 대한 기본 브라우저 동작을 방지한다.
        • 아래의 경우 <form> 내부의 버튼을 클릭 시 기본적으로 전체 페이지가 다시 로드되는 걸 방지해 준다.
    export default function Signup() {
      return (
        <form onSubmit={e => {
          e.preventDefault();
          alert('Submitting!');
        }}>
          <input />
          <button>Send</button>
        </form>
      );
    }

    클래스 컴포넌트에서의 이벤트

    • 클래스형 컴포넌트에서는 this를 사용해야 함수를 찾아갈 수 있다.
      • state와 props와 동일
    <button onClick={this.printConsole}>printConsole2</button>
    
    <button onClick={this.handleButton}>handleButton</button>

    함수에서 this 사용하기 (클래스 컴포넌트)

    • bind 사용하기
    • 화살표 함수 이용하기
    import { Component } from "react";
    
    class Counter extends Component {
      //기본적으로 생성자 만들고 this.state를 사용해야 한다.
      //   constructor(props) {
      //     super(props);
    
      //     //this.state.number의 초기값 할당.
      //     this.state = {
      //       number: 0,
      //     };
    
      //     //바인딩
      //     this.handleIncrement = this.handleIncrement.bind(this);
      //   }
      //   handleIncrement() {
      //     // this.state.number++; 이렇게 작성하면 안된다.(직접적으로 변경하면 안된다.)
      //     this.setState({ number: this.state.number + 1 }); //setState를 사용해야 한다.
      //   }
    
      //화살표 함수에서는 생성자와 this 없이 사용 할 수 있다.
      state = {
        number: 0,
      };
    
      handleDecrement = () => {
        //setState는 호출 직후에 상태가 바로 업데이트 되지 않는다.
        //비동기적으로 동작한다는 뜻
        //React는 여러 setState 호출을 일괄 처리한다.
        this.setState({ number: this.state.number - 1 }); //1번 setState
        this.setState({ number: this.state.number - 1 }); //2번 setState
        //2의 setState가 1의 setState의 결과를 기반으로 동작하지 않는다.
    
    //===화살표 함수 형태로 사용. 밑에 있는 방법이 좀 더 올바를 방법이다. 위의 코드처럼 직접적으로 
    //===변경하게 되면 해킹 당했을 때 위험부담이 더 커진다.
        this.setState((prevState) => ({ number: prevState.number - 1 })); //이전 상태를 기억한다.
        this.setState((prevState) => ({ number: prevState.number - 1 })); //이전 상태를 기억한다.
      };
      render() {
        return (
          <div>
            <h1>{this.state.number}</h1>
            <button onClick={this.handleIncrement}>증가</button>
            <button onClick={this.handleDecrement}>감소</button>
          </div>
        );
      }
    }
    export default Counter;

    공식문서에 나온 요약 내용

    - You can handle events by passing a function as a prop to an element like "<button>".
    - Event handlers must be passed, not called! "onClike={handleClick}", not "onClick={handleClick()}.
    - You can define an event handler function separately or inline.
    - Event handlers are defined inside a component, so they can access props.
    - You can declare an event handler in a parent and pass it as a prop to a child.
    - You can define your own event handler props with application-specific names.
    - Events propagate upwards. Call "e.stopPropagation()" on the first argument to prevent that.
    - Events may have unwanted default browser behavior. Call "e.preventDefault()" to prevent that.
    - Explicitly calling an event handler prop from a child handler is a good alternative to propagation.

    https://react.dev/learn/responding-to-events#adding-event-handlers

     

    Responding to Events – React

    The library for web and native user interfaces

    react.dev


    state와 setState

    state

    • React에서 앱의 유동적인 데이터를 다루기 위한 객체
    • 계속해서 변하는 특정 상태
    • 상태에 따라 다른 동작을 함
    • 왜 사용하나?
      • State가 변경될 시 자동으로 재랜더링 되기 때문
      • 이 점이 변수와는 다른 점
    • setState 메서드를 사용하여 상태를 변경할 수 있다.
    Components often need to change what's on the screen as a result of an interatction. Typing into the form should update the input field, clicking "next" on an image carousel should change which image is displayed, clicking "buy" should put a product in the shopping cart. Components need to "remember" things: the current input value, the current image, the shopping cart. In React, this kind of component-specific memory is called state

    https://react.dev/learn/state-a-components-memory

     

    State: A Component's Memory – React

    The library for web and native user interfaces

    react.dev


    state VS props

    • props: 부모 컴포넌트에서 자식 컴포넌트에 데이터 전달 시 사용(읽기 모드)
    • state: 특정 컴포넌트가 갖는 상태(값)
      • 컴포넌트 내부에서 선언되고 내부에서 값을 변경함

    주의할 점

    • state는 원칙적으로 클래스형 컴포넌트에서만 사용가능
    • 직접 this.state를 변경하지 말 것!
      • 항상 setState를 사용
    • setState는 비동기적으로 동작하므로, 이전 상태를 기반으로 다음 상태를 계산할 때 함수 형태의 setState를 사용

    클래스형 컴포넌트

    import { Component } from "react";
    
    class EventClass extends Component {
      //생성자
      constructor(props) {
        super(props); //부모 클래스인 component의 생성자 호출
    
        this.handleClick = this.handleClick.bind(this);
      }
    
      //일반 함수
      //binding 해줘야 한다.
      //   constructor(props) {
      //     super(props); //부모 클래스인 component의 생성자 호출
    
      //     this.handleClick = this.handleClick.bind(this);
      //   }
      handleClick() {
        console.log(this);
        alert("클래스형 컴포넌트");
      }
    
      //화살표 함수
      //binding을 안해도 된다.
      handleClick2 = () => {
        console.log("화살표 함수", this);
        alert("클래스형 컴포넌트 2번");
      };
    
      render() {
        return (
          <>
            <button onClick={this.handleClick}>클릭class</button>
            <button onClick={this.handleClick2}>클릭class 2번</button>
          </>
        );
      }
    }
    
    export default EventClass;

    함수형 컴포넌트 useState

    하기 전에 앞서 Hook을 먼저 알아보자

     

    Hook

    • 리액트(React) 훅은 2018년 10월에 React컨퍼런스에서 처음으로 소개
    • 2019년에 React의 16.8버전에서 공식적으로 소개되고 사용
    • React의 새로운 기능
    • 클래스 컴포넌트에서만 가능했던 state(상태관리)와 lifecycle(라이프사이클)이 가능하도록 돕는 기능

    Hook 사용 규칙

    • 최상위 단계에서만 호출 가능
      • 최상위 컴포넌트가 아니다.
      • 반복문, 조건문, 중첩된 함수 내부에서 호출하면 안 되는 것
    • Hook은 오로지 React 함수형 컴포넌트 안에서만 호출이 가능하다.
    • 커스텀 훅 이름은 "use"로 시작(권장)

    Hook 종류

    • useState() : 상태 관리를 위한 가장 기본적인 훅
    useState declares a state variable that you can update directly.
    function ImageGallery(){
    	const[index, setIndex] = useState(0);
    • useState 함수의 인자에는 상태의 초기값
      • useState의 초기값은 숫자일 수도, 문자일 수도, 배열일 수도 있다. 즉, 값의 형태가 자유롭다
    • useState 함수는 배열을 반환
      • 첫 번째 원소: 현재 상태
      • 두 번째 원소: 상태를 바꿔주는 setter 함수
      • number라는 변수를 만들고 setNumber을 통해 number의 값을 설정해 줄 수 있다.
    import { useState } from "react";
    
    export default function CounterFunc() {
      //   const state = useState();
      //     //[undefined, f]가 나온다.
      //     //undefinded는 우리가 필요한 초기값을 넣으면 되고, f에는 함수를 넣으면 된다.
      //   console.log(state);
    
      const [number, setNumber] = useState(0);
      console.log(number);
    
      function handleIncrement() {
        setNumber(number + 1);
      }
      const handleDecrement = () => {
        setNumber(number - 1);
      };
    
      return (
        <div>
          <h1>{number}</h1>
          <button onClick={handleIncrement}>증가</button>
          <button onClick={handleDecrement}>감소</button>
        </div>
      );
    }
    • useEffect(): 컴포넌트가 렌더링 될 때마다 특정 작업을 수행하도록 설정할 수 있는 훅
    'useEffect' connects a component to an external system
    function ChatRoom({ roomId }) {
      useEffect(() => {
        const connection = createConnection(roomId);
        connection.connect();
        return () => connection.disconnect();
      }, [roomId]);
    • useContext(): 리액트에서 전역적으로 접근 가능한 데이터나 함수를 관리하고, 필요한 컴포넌트에서 그 값을 바로 가져와 사용할 수 있게 도와주는 훅
    'useContext' reads and subscribes to a context
    function Button() {
      const theme = useContext(ThemeContext);
      // ...
    • useReducer(): 복잡한 컴포넌트 상태 로직을 리듀스 함수를 통해 관리할 수 있는 훅
    'useReducer' declares a state variable with the update logic inside a reducer function
    • useMemo(): 메모이제이션을 통해 함수의 리턴 값을 재사용할 수 있게 해주는 훅
    'useMemo' lets you cache result of an expensive calculation
    function TodoList({ todos, tab, theme }) {
      const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
      // ...
    }
    • useCallback(): 함수를 메모이제이션하여 불필요한 렌더링을 줄이게 해주는 훅
    'useCallback' lets you cache a function definition before passing it down to an optimized component
    • useRef(): 참조(reference)를 생성하고 관리할 수 있는 훅(DOM 접근, 변수 보존 등)
    'useRef' declares a ref. You can hold any value in it, but most often it's used to hold a DOM node.
    function Form() {
      const inputRef = useRef(null);
      // ...
     

    Built-in React Hooks – React

    The library for web and native user interfaces

    react.dev


    공식문서에 나온 요약 내용

    - Use a state variable when a component needs to "remeber" some information between renders.
    - State variables are declared by calling the "useState" Hook.
    - Hooks are special functions that start with "use". They let you "hook into" React feature like state.
    - Hooks might remind you of imports: they need to be called unconditionally. Calling Hooks, includeing "useState", is only valid at the top level of a component or another Hook.
    - The "useState" Hook returns a pair of values: the current state and the function to update it.
    - You can have more than one state variable. Internally, React matches them up by their order.
    - State is private to the component. If you render it in two places, each copy gets its own state.

    https://github.com/DongHo-Kang/KDT-8-web/tree/94422cc6387a49d57ea61f51f659bfc2b8acab1e/react_basic

    React-Event Handling, 합성 이벤트, state, setState, useState, Hook

    728x90
Designed by Tistory.