Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inputFile.current.click() inside useEffect doesn't work in safari

I have <input type="file" /> and want to trigger .click() on that input. Everything works fine in chrome, firefox, edge but problem exists in safari.

When I click on button to trigger inputFile.current.click() - it works. But when it happens inside useEffect/useLayoutEffect - it doesn't work (I've tried adding timeouts and it also didn't help).

Working example to reproduce problem: https://codesandbox.io/s/react-hooks-counter-demo-forked-49n2t?file=/src/index.js

As less code as possible to present problem

import React, { useCallback, useState, useEffect, useLayoutEffect, useRef } from 'react';
import { useRecoilState } from 'recoil';
import { requestedNewCanvasObjAtom } from '../SlidesState/slidesAtoms';

const Slide: React.FC = () => {
  const [trigger, setTrigger] = useState(false);
  const [requestedNewCanvasObj] = useRecoilState(requestedNewCanvasObjAtom);
  const inputFile = useRef(null);

  useLayoutEffect(() => {
    console.log('IT IS HERE WHEN EXPECTED BUT IT DOES NOT WORK TOO');
    inputFile.current.click();
  }, [requestedNewCanvasObj]);

  useLayoutEffect(() => {
    console.log('IT WORKS');
    inputFile.current.click();
  }, [trigger]);

  const triggerUpload = useCallback(() => {
    if (inputFile && inputFile.current) {
      console.log('IT WORKS');
      inputFile.current.click();
    }
  }, []);

  return (
    <>
      <button onClick={triggerUpload}>Click</button>
      <button onClick={() => setTrigger(true)}>Update state to trigger input click</button>
      <input type="file" id="file" ref={inputFile} />
    </>
  );
};

export default Slide;

THIS QUESTION WAS UPDATED - simplified problem without recoil was solved by useLayoutEffect but turns out that my problem is more complex

like image 908
Żywy Avatar asked Jan 23 '26 05:01

Żywy


1 Answers

The on click event is fired but the finder doesn't show up. Use useLayoutEffect. It fires synchronously after all DOM mutations:

  useLayoutEffect(()=> {
    if (inputRef && inputRef.current) {
      inputRef.current.click();
    }
  }, [count])

In other browsers like Chrome, useEffects and useLayoutEffect will work to show the finder. But in Safari, only the useLayoutEffect will work.

like image 166
lissettdm Avatar answered Jan 25 '26 19:01

lissettdm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!