useEvent 제안의 배경과 중단된 이유
📌 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월 현재 개발 완료되지 않음)