Raul
Raul

Reputation: 3081

React - Fetch data in the parent or inside its childs?

Note: I am not using Redux (only Context + Hooks)

Introduction

I have a screen "Profile", that renders a TabView.

This TabView, renders two components as scenes:

  1. UserPosts
  2. UserInformation

My Profile screen, fetches the user data from my database, as it has to render some stuff that depends on this data.

Also, it is passed down via props to my "UserInformation" component, as it just renders the user data. So... there is no data fetching in my "UserInformation" component.

In the other hand, my "UserPosts" component is responsible of fetching the user posts, as it renders a component "UserPostsGrid" which renders those posts with pagination (endless FlatList).

Note: Data fetching is performed in custom hooks, not directly inside the component (also, those hooks manages the respective stateful data).

Problem

The main problem comes when I need to refresh the user data and the user posts when the user pull-to-refresh inside the "Profile" screen.

There is no problem for this screen to fetch the user data, as I have said before the "Profile" screen is responsible of that action.

But the posts are the stateful data of my child...

Multiple solutions?

I have thought to solve this problem using the current solution:

React.forwardRef() + React.useImperativeHandle()

With this, I will be able to pass a ref to my "UserPosts" and use imperative programming for accessing the data fetching method: userPostsRef.current.refreshPosts();

I have never seen other scenarios for solving this problem like this, but it should work. Instead, other coders implement a ContextProvider to handle all the data and be able to access it wherever they want. The main problem I notice here is: extra memoization + extra re-renders.

Another solution might be to implement all the data fetching inside the parent, and pass the respective callbacks via props to the child. The main problem I notice here is that we are creating some kind of "God Component" and we might have multiple lines of code...

My question

Is it an anti-pattern or a bad practice to implement the first solution ?

Upvotes: 1

Views: 2037

Answers (1)

kca
kca

Reputation: 6055

To answer your question:

Yes, it is an antipattern in React, because React is built around the idea that you specify the state of your app, and then let React render the components depending on this given state.

If something should change, you are supposed to specify a new state that represents the difference to the old state.

Refs should only be used if there is no other option. Basically, if you use Refs you say "I don't want to use React for this specific part of my code".

As always, imperative code using refs should be avoided in most cases

To use state instead of commands:

I would approach this kind of problem by trying to translate the imperative action into some state of information.

  • The user says "get me the latest data", that is a command, i.e. imperative.
  • Now I would ask "what is the user telling me about the state of the data right now ?"
  • An answer would be "this data is not up to date anymore", and this can be expressed as a state, and passed around via props.

A solution for your problem:

E.g. you might use a prop needsUpdate, which is set to true when the data should be updated, and to false when fetched.

To avoid unnecessary renders (setting needsUpdate = false would cause another call of e.g. useEffect, even if nothing happens there), I probably would use a child component prop like latestUpdateRequest and a child state like latestUpdate which holds a counter or timestamp, and then compare if(latestUpdateRequest > latestUpdate).

To inform the parent about the change just pass a callback function like dataUpdated() as a prop.

Upvotes: 1

Related Questions