관리 메뉴

웹개발자의 기지개

[React] 이벤트 핸들러 , 클로저, currying - 매개변수 처리하기 본문

javascript/React

[React] 이벤트 핸들러 , 클로저, currying - 매개변수 처리하기

웹개발자 워니 2025. 10. 9. 15:06

 

1. 단일 매개변수 전달하기

1
2
3
4
5
6
7
8
9
const onIncrease = (num) => {
  console.log(`+${num} 했다.`);
};
 
return (
  <div>
    <button onClick={() => onIncrease(1)}>Plus 1</button>
  </div>
);
cs

 


onClick={onIncrease(1)} ❌ 이렇게 쓰면 렌더링 시점에 함수가 바로 실행돼 버립니다.
따라서 () => onIncrease(1) 처럼 익명 화살표 함수로 감싸서 클릭할 때 실행되게 해야 합니다.

 

 

2. 여러 개의 매개변수 전달하기

1
2
3
4
5
6
7
8
9
10
11
const onIncrease = (a, b, c) => {
  console.log(`매개변수: ${a}, ${b}, ${c}`);
};
 
return (
  <div>
    <button onClick={() => onIncrease(1020'React')}>
      여러 매개변수 전달
    </button>
  </div>
);
cs

 

 

클릭 시 onIncrease(10, 20, 'React')가 실행되고, 콘솔에

 

매개변수: 10, 20, React

 

 

3. 매개변수와 event 객체를 함께 전달하기

React의 이벤트 핸들러에서는 onClick={(e) => ...} 형태로 이벤트 객체도 사용할 수 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
const onIncrease = (num, msg, e) => {
  console.log(`num: ${num}`);
  console.log(`msg: ${msg}`);
  console.log(`클릭한 버튼: ${e.target.textContent}`);
};
 
return (
  <div>
    <button onClick={(e) => onIncrease(5'Hello', e)}>
      Click Me
    </button>
  </div>
);
cs

 

 

  • 이벤트 객체는 마지막에 전달하는 것이 일반적입니다.
  • React의 SyntheticEvent는 자동으로 전달되지 않기 때문에 직접 넘겨줘야 합니다.

 

 

 

4. 미리 매개변수가 정해진 핸들러 만들기 (커링 방식)

복잡한 상황에서는 커링(currying) 또는 bind를 이용해 미리 함수를 생성해 둘 수도 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
const createHandler = (num, msg) => (e) => {
  console.log(`num: ${num}, msg: ${msg}`);
  console.log(`이벤트 타겟: ${e.target.textContent}`);
};
 
return (
  <div>
    <button onClick={createHandler(99'커링')}>
      커링 방식 버튼
    </button>
  </div>
);
cs

 

이 방식은 리스트 렌더링 시 여러 버튼마다 다른 매개변수를 줘야 할 때 특히 유용합니다.

 

onClick={() => func(param)} 가장 기본적이고 많이 쓰는 방식
onClick={(e) => func(param, e)} 매개변수와 이벤트 객체를 함께 쓸 때
onClick={func.bind(null, param)} 옛날 방식 (지금은 잘 안 씀)
onClick={createHandler(param)} 커링으로 미리 함수 생성해서 깔끔하게 작성 가능

 

 

1. 기본 예제: 매개변수로 상태 변경하기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React, { useState } from 'react';
 
function Counter() {
  // 1️⃣ 상태 선언 (초깃값은 0)
  const [count, setCount] = useState(0);
 
  // 2️⃣ 매개변수를 받아서 상태값을 변경하는 함수
  const onChangeCount = (num1, num2) => {
    setCount((prev) => prev + num1 + num2); // 이전 상태값에 num1 + num2를 더함
  };
 
  return (
    <div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
      <h2>현재 카운트: {count}</h2>
 
      {/* 3️⃣ 매개변수를 전달하는 onClick */}
      <button onClick={() => onChangeCount(12)}>
        +1+2 증가 (총 +3)
      </button>
 
      <button onClick={() => onChangeCount(510)} style={{ marginLeft: '10px' }}>
        +5+10 증가 (총 +15)
      </button>
 
      <button onClick={() => setCount(0)} style={{ marginLeft: '10px' }}>
        초기화
      </button>
    </div>
  );
}
 
export default Counter;
cs

 

 

 

  • onClick={() => onChangeCount(1, 2)} 클릭
  • onChangeCount(1, 2) 실행 → setCount(prev + 3) 호출
  • 화면이 다시 렌더링되고 count 값이 바뀐 상태로 표시됨

 

2. 이벤트 객체와 함께 쓰기 (옵션)

이벤트 객체도 필요하다면 아래처럼 세 번째 인자로 받을 수 있습니다.

 

1
2
3
4
5
6
7
8
const onChangeCount = (num1, num2, e) => {
  console.log('클릭한 버튼:', e.target.textContent);
  setCount((prev) => prev + num1 + num2);
};
 
<button onClick={(e) => onChangeCount(23, e)}>
  이벤트도 함께 전달
</button>
cs

 

 

3. 커링 방식으로 더 깔끔하게 만들기

버튼이 많아질 경우에는 함수 감싸는 부분이 길어지는데, 커링(currying) 으로 정리할 수 있습니다

 

1
2
3
4
5
6
const createHandler = (num1, num2) => (e) => {
  console.log('클릭한 버튼:', e.target.textContent);
  setCount((prev) => prev + num1 + num2);
};
 
<button onClick={createHandler(37)}>+3 +7 증가</button>
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Counter() {
  const [count, setCount] = React.useState(0);
 
  // ⚙️ 커링/부분 적용: num1, num2를 확정하고, 클릭(e) 시 실행할 함수를 반환
  const createHandler = (num1, num2) => (e) => {
    setCount((prev) => prev + num1 + num2);
    // e도 쓸 수 있어요: console.log(e.target.textContent);
  };
 
  return (
    <div>
      {/* 렌더링 시점: createHandler(3,7)가 '클릭용 함수'를 만들어서 onClick에 전달 */}
      <button onClick={createHandler(37)}>+3 +7</button>
      <button onClick={createHandler(1020)}>+10 +20</button>
    </div>
  );
}
cs

 

  • 렌더 타이밍: createHandler(3,7) → (e) => { ... } 새 함수 생성
  • 클릭 타이밍:새 함수가 실행되며 setCount가 호출

즉, 렌더할 때는 “만들기”만, 클릭할 때는 “실행”만 일어나요.
JSX에는 () => onIncrease(3,7) 같은 화살표가 사라져서 한결 깔끔해집니다.

 

* 인자 하나씩 순서대로 받고 마지막에 e 받기 - 커링 기법

1
2
3
4
5
6
7
8
// a를 받고 → b를 받고 → 마지막에 클릭 이벤트(e)를 받음
const createAdder = (a) => (b) => (e) => {
  console.log('clicked:', e.target.textContent);
  setCount((prev) => prev + a + b);
};
 
// 사용
<button onClick={createAdder(5)(9)}>+5 +9</button>
cs

실무에선 보통 (A)처럼 두어 개의 인자 + 마지막에 (e) 정도로 충분합니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const withParams = (id, step) => (e) => {
  console.log('id:', id, 'step:', step);
  // e 사용 가능
};
<button onClick={withParams(423)}>증가</button>
 
 
const items = [{ id: 1 }, { id: 2 }, { id: 3 }];
 
return (
  <ul>
    {items.map((item) => (
      <li key={item.id}>
        <button onClick={withParams(item.id, 5)}>
          {item.id}에 +5
        </button>
      </li>
    ))}
  </ul>
);
cs

 

items 의 map() 함수 이용

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React from 'react';
 
export default function CounterCurried() {
  const [count, setCount] = React.useState(0);
 
  // 부분 적용/커링: 매개변수 묶고 마지막에 (e) 받는 패턴
  const incBy = (a, b) => (e) => {
    console.log('clicked:', e.target.textContent);
    setCount((prev) => prev + a + b);
  };
 
  // 완전 커링 느낌: (a)(b)(e)
  const incByFully = (a) => (b) => (e) => {
    setCount((prev) => prev + a + b);
  };
 
  return (
    <div style={{ fontFamily: 'sans-serif', padding: 16 }}>
      <h3>count: {count}</h3>
      <button onClick={incBy(37)}>+3 +7</button>
      <button onClick={incBy(1020)} style={{ marginLeft: 8 }}>
        +10 +20
      </button>
      <button onClick={incByFully(1)(2)} style={{ marginLeft: 8 }}>
        +1 +2 (fully curried)
      </button>
      <button onClick={() => setCount(0)} style={{ marginLeft: 8 }}>
        reset
      </button>
    </div>
  );
}
cs

 

 

[초간단 정리하기]

 

const withParams = (x, y) => (e) => {  /* x,y,e 사용 */  };
<button onClick={withParams(10, 20)}>OK</button>

 

 

 

Comments