Refactor multiple useEffects

248 Views Asked by At

I need to fetch multiple items (about 6)with different ID's passed via props, names are made up, f.e. headerId, bodyId, footerId.

I made an useEffect for each one:

useEffect(() => {
    const getHeader = async () => {
        const header = await api.fetch(props.headerId);
        setHeader(header);
    }
    getHeader();
}, [props.headerId])

What I don't like is that now I have same useEffects just with different prop, could I somehow merge all of them or this is the way I should do it.

2

There are 2 best solutions below

0
On

Passing multiple properties into array within useEffect, like:

}, [props.headerId, props.bodyId]);

will call the function if even one of the passed properties have changed. I believe you don't really want to call every async request to API (for new header, new body and so on) even if only one prop has changed.

Using multiple useEffect allows you to call only that particular request, that it's prop has changed.

0
On

You can make a higher order function that can be called with the state setter function and the prop name, that gets passed to useEffect:

const setAPIState = () => (prop, setter) => {
  api.fetch(props).then(setter);
};
// Then replace your original code with
const propsAndSetters = [
  [props.headerId, setHeader],
  [props.bodyId, setBody],
  // ...
];
for (const [prop, setter] of propsAndSetters) {
  useEffect(setAPIState(prop, setter), prop);
}

It's still somewhat repetitive, but since you want separate API calls for each different prop, you need a different useEffect for each one.