Reputation: 540
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()))
};
}
Upvotes: 11
Views: 39369
Reputation: 15652
To have the useEffect
hook called when state updates, you'll need to include the relevant state variables in the dependency array of useEffect
(the second argument passed to useEffect
), which it seems you've attempted.
To address useEffect
being called on every render of the component: this is happening because a value in the dependency array (getUploads
) is changing, or being redefined, on every render. To fix this, you can use the useDispatch
redux hook instead of mapDispatchToProps
. The useDispatch
hook provides a stable reference (meaning it won't change and cause useEffect
to run) to the dispatch
function from the Redux store.
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
}
Upvotes: 14