Dalej poznajemy useEffect, na nieco znanym już nam przykładzie oraz dalej uczymy się pisać custom hooks. Do dzieła.
Ok, nasz dot:
return (
<div style={{
position: 'absolute',
backgroundColor: 'pink',
borderRadius: '50%',
opacity: 0.6,
transform: `translate(${position.x}px, ${position.y}px)`,
pointerEvents: 'none',
left: -20,
top: -20,
width: 40,
height: 40,
}} />
);
}
A teraz góra:
import { useState, useEffect } from 'react';
export default function App() {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
function handleMove(e) {
setPosition({ x: e.clientX, y: e.clientY });
}
window.addEventListener('pointermove', handleMove);
return () => {
window.removeEventListener('pointermove', handleMove);
};
}, []);
Jak to działa:
- Każdy setPosition wywołuje re-render
- useEffect działa tylko raz, ale wykonuje setPosition
- jako cleanup jest remove event listener
Ok, teraz napiszemy to sobie, ale jako custom hook:
import { useState, useEffect } from 'react';
export function useWindowListener(eventType, listener) {
useEffect(() => {
window.addEventListener(eventType, listener);
return () => {
window.removeEventListener(eventType, listener);
};
}, [eventType, listener]);
}
Ważne – custom hooki muszą zaczynać się od słówka use, inaczej nie moglibyśmy używać hooków Reacta poza funkcjami-komponentami na ich najwyższym (niezagnieżdżonym w niczmym) poziomie.
Teraz używamy tego hooka:
import { useState } from 'react';
import { useWindowListener } from './useWindowListener.js';
export default function App() {
const [position, setPosition] = useState({ x: 0, y: 0 });
useWindowListener('pointermove', (e) => {
setPosition({ x: e.clientX, y: e.clientY });
});
return (
<div style={{
position: 'absolute',
backgroundColor: 'pink',
borderRadius: '50%',
opacity: 0.6,
transform: `translate(${position.x}px, ${position.y}px)`,
pointerEvents: 'none',
left: -20,
top: -20,
width: 40,
height: 40,
}} />
);
}
Więcej useEffect oraz custom hooks już niedługo.