Reputation: 5073
edit: changed pretty much the whole body of this question
I am building a booking app. Tons of rerenders are happening and, following @jpmarks advice, I have tried to find out which useEffect could be the culprit, and think might be the piece of code below, which runs 24 times.
I have also uploaded all of the relevant components and console warnings to this repo, assuming that other components which render this may be affecting it.
useEffect(
() => {
console.log('useEffect ServicEstabelecimento ran') //runs 24 times
async function getOfferedServicesFromDB() {
const approved = await approvedBusinessService.doc(businessId)
const snapshotApproved = await approved.get()
if (snapshotApproved.exists && snapshotApproved.data().offeredServices) {
setOfferedServices(Object.values(snapshotApproved.data().offeredServices))
} else {
const pending = await businessPendingApprovalService.doc(businessId)
const snapshotPending = await pending.get()
if (snapshotPending.exists && snapshotPending.data().offeredServices)
setOfferedServices(Object.values(snapshotPending.data().offeredServices))
}
return
}
getOfferedServicesFromDB()
},
[
/* businessId, setOfferedServices */
],
)
//React Hook useEffect has missing dependencies:
//'businessId' and 'setOfferedServices'.
//Either include them or remove the dependency array
//Tried adding them separately or both, nothing changes
What I am trying to do here is see which services a business offers, getting that info from the database. If the business has been accepted or not yet, there's a change in how that's dealt with.
Upvotes: 4
Views: 694
Reputation: 13682
One possibility is that in Options.js
you are rendering ServiceEstabelecimento
multiple times using serviceList.map
. The serviceList
is set in the useEffect with serviceListService.collection().onSnapshot
callback. With this, naturally your useEffect will be called 24 times(if serviceList gets a value of 24 in snapshot callback)
Another possibility is that you are rendering ServiceEstabelecimento
with a ternary. This will unmount/re-mount the componentthe component based on the value of estabelecimento
.
const ContextOptionsEstabelecimento = React.createContext()
export const Options = () => {
const { estabelecimento, theme, offeredServices } = useContext(Context)
const [isConfiguring, setIsConfiguring] = useState(false)
const [serviceList, setServiceList] = useState([])
useEffect(() => {
const unsubscribeServices = serviceListService.collection().onSnapshot(snapshot => {
const services = snapshot.docs.map(collectIdsAndDocs)
setServiceList(services) //<-----see here
})
return () => {
unsubscribeServices()
}
}, [])
const serviceElements = serviceList.map(service => //<-----see here
!estabelecimento ? ( //<-----see here
<Service
key={service.id}
id={service.id}
name={service.name}
type={service.type}
title={service.info}
duration={service.duration}
/>
) : ( //<-----see here
<ContextOptionsEstabelecimento.Provider value={{ isConfiguring }} key={service.id}>
<ServiceEstabelecimento
key={service.id}
id={service.id}
name={service.name}
type={service.type}
title={service.info}
duration={service.duration}
/>
</ContextOptionsEstabelecimento.Provider>
),
)
return (
...
Make checks on the above and see how you go. Also share the complete repo(if possible) to debug further.
Also I see some architecting issues as I see large objects been used with multiple contexts. This will have risk of components re-rendering unnecessarily. I am assuming you are taking care of such kind of things.
Upvotes: 2
Reputation: 1539
I looked through your source code and it looks like the component is not responsible for the unneccessary renders. I recommend fixing the dependencies as your editor is telling you, see if that is fixing something. I strongly believe its your context that gets updated inside of one of your effects that causes the context to rerender the component. To find out what state from context is causing the renders you can use the useEffect on each of them to check.
const { theme, userObject, dateForRenderingTimeGrid } = useContext(Context);
useEffect(() => {
console.log("Theme updated");
}, [theme]);
useEffect(() => {
console.log("UserObject updated");
}, [userObject]);
useEffect(() => {
console.log("DateForRenderingTimeGrid updated");
}, [dateForRenderingTimeGrid ]);
Let me know what you are seing. If none of these are actually triggering an effect but you still see the renders, then you can be certain that its happening in your component
Upvotes: 3