Justin Seo
Justin Seo

Reputation: 93

React why does eventListener runs twice unless terminate on useEffect?

just got interesting phenomenon while coding.

I was trying to send request when I press 'enter' and found that 'keypress' eventListener runs twice.

so I figured out when I terminate keypress eventListener when component unmounts, the problem got fixed, but I just cant understand why this happens.

const inputRef = useRef(null);
    const fileRef = useRef(null);
    const [files, setFile] = useState([]);

    const sendMessage = useCallback(() => {
        if (inputRef.current.value === '' && files.length === 0) {
            return;
        }

        console.log('f', inputRef.current.value, files);
        if (files.length === 0) {
            AxiosClient.post('/general-msg', {
                orderId,
                recipient,
                content: inputRef.current.value
            });
            inputRef.current.value = '';
        } else {
            const messagePackage = new FormData();
            messagePackage.append('orderId', orderId);
            messagePackage.append('recipient', recipient);
            messagePackage.append('content', inputRef.current.value);

            files.map((file) => {
                return messagePackage.append('file', file);
            });

            AxiosClient.post('/message', messagePackage, {
                headers: {
                    'Content-Type': 'multipart/form-data'
                }
            });
            inputRef.current.value = '';
            setFile([]);
        }
    }, [files, inputRef, orderId, recipient]);

    const registerSendingTrigger = useCallback(
        (e) => {
            console.log('heelo');
            if (e.code === 'Enter') {
                console.log('sending...'); // sending logs twice unless I write below
                sendMessage();
            }
        },
        [sendMessage]
    );
    useEffect(() => {
        if (inputRef.current) {
            inputRef.current.removeEventListener('keypress', registerSendingTrigger);

            inputRef.current.addEventListener('keypress', registerSendingTrigger);
        }

        return () => inputRef.current.removeEventListener('keypress', registerSendingTrigger); // this part!!!!!!!!

        // why does send request gets twice when I delete return state??
    }, [inputRef, registerSendingTrigger]);
    useEffect(() => {
        if (fileRef) {
            fileRef.current.addEventListener('change', (e) => {
                if (!e.target.files[0]) {
                    return;
                }
                setFile((current) => {
                    return [...current, e.target.files[0]];
                });
            });
        }
    }, []);

Upvotes: 0

Views: 385

Answers (1)

TimmNL
TimmNL

Reputation: 216

useEffect is executed every time something in the dependency-array changes value. This means that in your case it will add another event-listener when registerSendingTrigger changes it value.

The misconception here is that useEffect represents the mount and unmount of React. It works like that if you have an empty dependency array, but will be executed more often when it is used with dependencies.

Check this for more information: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

Upvotes: 1

Related Questions