Search code examples
reactjsreact-hooksinfinite-loopredux-toolkitfilereader

Infinite loop when using dependency in useeffect


I'm trying to read image file and upload it to jsonserver using fileReader API with React-Reduxtoolkit, everything is ok but there is warning when using useeffect without 'productInfo' and 'dispatch' dependencies, but when I add them into dependency array, it generate an infinite loop and I dont understand why ?

function CreProducts(props) {
    debugger
    const dispatch = useDispatch();
    const productInfo = useSelector((state) => state.products.product);
    const [url, seturl] = useState([]);

    console.log(productInfo);

    function handleChange(e) {
        const { name, value } = e.target;
        const file = e.target?.files && e.target.files;
        // file handle.............................
        if (file) {
            const filelist = Array.from(file);
            readFile(filelist);
            return
        } else {
            dispatch(addProductInfo({ ...productInfo, [name]: value }));
        }
    }

    // read file .........................
    function readFile(files) {
        for (let item of files) {
            const reader = new FileReader();
            reader.onload = function (e) {
                let blob = e.target.result;
                seturl((prev) => [...prev, blob]);
            };
            reader.readAsDataURL(item);
        }
    }
    useEffect(() => {
        if (url.length !== 0) {
            dispatch(addProductInfo({ ...productInfo, 'pics': url }))
        }
    },[url, productInfo])
return(<>............</>)
  • am I using filereader api correctly compare to reality projects ?
  • correct way to solve my problem ? thank you for spend time on my issue

Solution

  • After the initial setup of the component, the component renders then this is what is occurring:

    render -> 
    ^  useEffect -> 
    |____url.length > 0 -> dispatch() [[ Dependecy changes here - forces rerender ]]
    |    url.length === 0 -> 
    |      handleChange ->
    |        readFile() ->
    |__________setUrl [[ Dependency Changes here - forces rerender ]]
    

    So you can see, once a change is detected, one or the other (either handleChange() or useEffect() always changes one of the depencecies - which causes the loop.

    You don't need to change state in useEffect() - dispatch the request in readFile just after setUrl(). But you will need to dispatch with blob rather than url as it won't be available in state yet.