TIL

useEvent 제안의 배경과 중단된 이유

Jenner 2025. 3. 10. 13:51

📌 1. useEvent란

- 참조 안정성 

- 최신의 상태

- 함수 참조 변경 불필요

 

이벤트 핸들러에서 상태값을 항상 최신의 상태로 유지할 수 있도록 도와주는 훅. 

useEvent로 감싸면 dependency에 특정 상태를 넣지 않아도 내부의 state가 항상 최신의 상태를 유지하며, 

useCallback에서 처럼 dependency에 상태를 넣어 재선언하지 않아도 된다. 

 

📌 2. useEvent제안의 배경

 

https://github.com/facebook/react/issues/14092#issuecomment-435907249

 

getState() hook proposal · Issue #14092 · facebook/react

useState() provided state value currently cannot be used in useEffect(fn, []) - (componentDidMount-like scenario) with asynchronous functions after state has been updated following the initial [] r...

github.com

✅ 14092 이슈

- getState훅을 제안함

 

const HooksComponent = () => {
    const [state, setState, getState] = useState({ val: 0 });

    useEffect(() => {
        setTimeout(() => setState({ val: 10 }), 100)
        setTimeout(() => {
            getState(state => {
                console.log('value: ', state.val)
            })
        }, 200)
    }, [])
}

 

 

- 이 제안의 등장 배경

 

const UserList = () => {
    const [users, setUsers] = useState([])
    useEffect(() => {
        const socket = io('/dashboard')
        socket.on('user:connect', (user) => {
            setUsers([...users, user])
        })
        socket.on('user:update', (user) => {
            let newUsers = users.map((u) => u.id == user.id ? user : u)
            setUsers(newUsers)
        }) 
    }, [])

    return (
        users.map(({id, email}) => (
            <tr key={id}>
                <td>{id}</td>
                <td>{email}</td>
            </tr>
        ))
    )
}

 

위의 코드를 보면 알 수 있다. 

 

- 코드의 역할

   - socket 통신의 이벤트 핸들러 등록

   - socket이 connect또는 update 이벤트가 발생 되었을 때 users의 상태를 설정해줌

   - socket이 재선언되지 않도록 useEffect는 빈 배열로 설정 

 

- 문제점 

   - socket 이벤트 핸들러 내부의 상태값 변경의 문제 

      useEffect내의 deps가 빈 상태를 유지하여 socket 연결의 사이드 이펙트를 방지하여야 한다. 

      그러나 이로 인해 상태값이 변경되지 않고 있다.

 

✅ RFC문서

https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md

 

rfcs/text/0000-useevent.md at useevent · reactjs/rfcs

RFCs for changes to React. Contribute to reactjs/rfcs development by creating an account on GitHub.

github.com

 

function Chat() {
  const [text, setText] = useState('');

  // 🟡 A different function whenever `text` changes
  const onClick = useCallback(() => {
    sendMessage(text);
  }, [text]);

  return <SendButton onClick={onClick} />;
}

 

- 문제점 

   - onClick함수가 리렌더링마다 재 선언 됨 

   - useCallback으로 감싸보아도 동일 (text가 변경되었기 때문) 

 

- useEvent의 활용

  // ✅ Always the same function (even if `text` changes)
  const onClick = useEvent(() => {
    sendMessage(text);
  });

   

   - onClick함수를 useEvent로 감싸면 항상 동일한 함수를 유지하며 내부의 상태는 항상 새로운 상태를 보장 

 

 

📌3. useEvent가 중단된 이유

 

https://github.com/reactjs/rfcs/pull/220#issuecomment-1259938816

 

RFC: useEvent by gaearon · Pull Request #220 · reactjs/rfcs

In this RFC, we propose a useEvent Hook. It lets you define event handlers that can read the latest props/state but have always stable function identity. Event handlers defined with useEvent don...

github.com

 

 

  • 현재 useCallback을 사용하는 모든 함수를 useEvent로 감싸는 강한 인센티브가 생길 가능성
  • 그러나 함수의 identity(식별성)가 중요한 경우에는 올바른 시맨틱이 아님
  • useEvent는 그 안으로 흐르는 값들의 reactivity(반응성)를 "지워버리기" 때문에, 어디에 적용하는 것이 적절한지에 대한 추가적인 제한 필요
  • 대부분의 경우, 최종 소비 측(예: 이벤트 함수가 호출되는 Effect)만이 함수 값의 반응성을 "신경 쓰는지" 여부를 확실히 알 수 있음
  • 자동 메모이제이션 컴파일러를 개발중에 있음(2025년 3월 현재 개발 완료되지 않음)