Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useEffect only if state changed

I have useEffect which calls an action from redux to fetch uploads

useEffect(() => {
    getUploads()
}, [getUploads])

However, I only want to fetch when the state changes, not fetch everytime the component renders. I have mapped the state like:

{filteredUploads.map((image, i) => { return (...) })}

I have tried to add getUploads, filteredUploads, filteredUploads.length as dependency array. None of it worked.

My redux-action:

export const getUploads = () => async dispatch => {
    try {
        dispatch({ type: 'LOADING', payload: true })

        const res = await axios.get('/uploads/myuploads')
        dispatch({
            type: GETMYUPLOAD_SUCCESS,
            payload: res.data
        })

    } catch (err) {
        const error = err.response.data.error[0].msg

        dispatch(setAlert(error, 'danger'))
    }
}

mapStatetoProps:

function mapStateToProps(state) {
    const { myuploads, searchField } = state.useruploads;
    return {

        searchField: state.useruploads.searchField,

        filteredUploads: myuploads.filter((upload) => upload.caption.toLowerCase().includes(searchField.toLowerCase()))
    };
}
like image 364
Lokesh Bajracharya Avatar asked Apr 27 '20 06:04

Lokesh Bajracharya


1 Answers

To have the useEffect hook called when state updates, just include the relevant state variables in the dependency array of useEffect (the second argument passed to useEffect).

To address useEffect being called on every render of the component: this is happening because getUploads gets redefined on every render. To fix this, you can use the useDispatch redux hook. This is instead of (and assuming you are currently using) mapDispatchToProps.

Here's a full example:

import { useDispatch } from 'react-redux'
import { getUploads } from "./redux-actions";


const MyComponent = props => {
    const dispatch = useDispatch();
    
    const [state, setState] = React.useState({});
    
    useEffect(() => {
        dispatch(getUploads());
    }, [dispatch, state]);

    // rest of component
}
like image 144
Henry Woody Avatar answered Nov 12 '22 14:11

Henry Woody