I’m using function components and hooks.
I have a hook that sends REST request to fetch a set of application data which involves multiple params (such as userId
, productId
etc) from an object in application state.
This hook uses a useEffect()
along the lines of:
useEffect(() => {
fetch()
…
}, [objectInState]); // {user: {id: ‘007’}, product: {id: 008}}
If the id
of any resource change, I want to send this request again, hence the [objectInState]
The problem came up when I try to set up URL based routing.
When I set initial state based on id
’s from URL, the useEffect
hook triggers and sends one request to fetch common app data as expected.
The problem is, each component responsible for rendering particular resource in URL params (user component, product component etc) then sends a REST request on their own to fetch the details of it’s resource, and expands the details of resource in state to become something like
// {user: {id: ‘007’, name: ‘John Doe’, email:’’}, product: {id: 008, name: ‘unicorns’, price: ‘1$’}}
but this changes are triggering the useEffect
that is fetching the same application data again multiple times.
I do want to fetch the application data if there is an actual change in the id
’s, for example
{user: {id: ‘007’, name: ‘John Doe’, email:’’}…
changes to
{user: {id: ‘008’, name: ‘John Wick’, email:’’}
But not when
{user: {id: ‘007’}…
is expanded to {user: {id: ‘007’, name: ‘John Doe’, email:’’}
by other components.
When I am expanding a current object in state from a component, if I can tell react to not trigger useEffect
’s listening to that param with something like {silent: true}
this problem can be avoided.
How can I make the useEffect()
not trigger again in such cases?
Or is there another way to implement such functionality?
From what you described, you should separate the object into different useStates.
Use something like:
const [user, setUser] = useState({});
const [product, setProduct] = useState({});
/* one useEffect to get the user */
useEffect(() => {
const user = fetchUser(userIdFromUrl);
setUser(user);
}, [userIdFromUrl]);
/* one useEffect to get the product */
useEffect(() => {
const product = fetchProduct(productIdFromUrl);
setProduct(product);
}, [productIdFromUrl]);
You can even later put the useState and useEffect statements in an custom hook at will.
NOTE fetch calls are simplified for example purposes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With