[포스코x코딩온] 웹개발자 풀스택 부트캠프8기

[포스코x코딩온] React-Event Handling, 합성 이벤트, state, setState, useState, Hook

항상 발전하는 개발자 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