I would like to know of a good way to organize reactfire hooks (such as useUser or useFirestoreCollectionData) in a medium-sized application:
I could put hooks in a top-level component, and pass this information as props down to subcomponents (or use a Context to store state).
I could put hooks within each component when needed, so I would end up with multiple useUser or useFirestoreCollectionData hooks.
The second approach decouples some of the components, which is nice since our project is under active development.
However, I am not sure if reactfire or firebase client library has built-in deduplication, compared to libraries such as SWR or react-query. I would prefer to minimize unnecessary reads.
I like to use a offline first approach when using the Firebase databases. None of the awailable libraries could fit our needs so I made my own list of providers where all of them are decoupled. The main goal was:
to have all data awailable offline no matter if the app is online or not (this also increases response time for users)
to persist realtime listeners for RTDB and Firestore
when you have for example a list and go to a single item and back you probably don't want to stop the listener when leaving that list component and start it again when comming back. If you stop and start it the firebase SKD will load all data from the database.
You can find the providers and an example app here.
Related
I'm working with a react app and currently working with a feature. The main task is showing some charts by getting data from API. And these charts will show the last 30 minutes' data.
I have questions,
In this situation, is it necessary to store these data in the state by Redux, though it can be handled at components very easily? And every time I refresh or request, I get new data (log base data).
When do we make the mind to store data in state and when not?
A redux store is a singleton, thus a single source of truth that can be made available to all components in the whole react application. If your state is intended only for one react component then you don't need a redux store. A useReducer react hook allows to well reproduce the redux pattern in a single component. Stick with a useReducer hook for a single component and use redux library for a store available to an app composed of several components.
Redux is not designed for the specif role of a special type of data.
You can use still store your temporary (30 min) data into redux, and use it to cross your feeling the same as the rest of your data.
But in this case, you might need to reset data after 30 minutes or invalidate your cache, keep your eye in react-query and RTK-query handling these types of actions more easily for you.
If data is being used for many states or those data are being used by many components then you should use redux. You can still go without redux, it is up to you after all.
If you have various components and routes then redux will help you to reduce the codes and also make the codes simpler.
Redux will give the one store for all the components in the project to store and access the data which is better then context or props tricks.
Also if you want to achive something like if user opened two different tabs. Let it be same page or two different pages of your website and if user done an action on page A and you want that page A or page B opened in another tab should get that update then redux can let you achieve that. Context and props passing are not useful in this case.
https://redux.js.org/faq/general#when-should-i-use-redux
Redux is most useful when in cases when:
You have large amounts of application state that are needed in many places in the app
The app state is updated frequently
The logic to update that state may be complex
The app has a medium or large-sized codebase, and might be worked on by many people
You need to see how that state is being updated over time
currently I am using redux in different projects for state management. A few days back, I listened about react-query which is also used for state management and provides caching and async fetching. I am trying to figure out the main difference between these two libraries.
Where I should use react-query and in which cases I need redux.
React-query is what you would call a specialized library. It holds an api cache for you - nothing else. And since it is specialized, it does that job quite well and requires less code.
Redux on the other hand gives you tools to just about store anything - but you have to write the logic. So you can do a lot more in Redux, but you'll have to potentialy write code that would not be necessary with a specialized library.
You can use them both side-by-side: api cache in react query, rest of your global state in Redux.
That said, the official Redux Toolkit also ships with an api cache abstraction RTK Query since version 1.6 with a similar feature set as React Query, but some different concepts overall - you might also want to check that out.
react-query is designed to deal with data that is stored on a remote server. To access this data, your app needs to use asynchronous requests. This is where you probably want to deal with caching, loading state, network failures, etc.
That is where react-query shines.
Redux on the other ends deals with data on the client-side. For example the content of a text input or the state of a modal. You don't need to deal with network-related issues. But you do need to deal with complex sequences of causes and effects.
That is where redux shines
Redux and react-query are 2 very different things: react-query is used for data synchronization, Redux is a global state manager. react-query is used to keep synch all your apps to the same db, Redux is used to share a part of the app state to all the components that need to read that state.
An example: I have an app to chat with other users. With react-query I keep all the apps synch with all the messages users received, then I store the messages in Redux in order to have messages on chat page and on history chat page.
React Query manages Server State. Its main function is to handle functions between Server and client.
Redux handles client-state. Redux can be used to store asynchronously Data.
So, they have their unique role at different levels and both can be used side by side.
React-Query = server state library(save/cache api response)
Redux = client state library(globally accessible client state
should be stored).
We should distinguish between two kind of states, client state & server (or remote) state:
client state contains:
locally created data that has not yet been persisted to the server.
UI state that handles active routes, selected tabs, spinners, pagination controls, and so on.
server state is everything related to:
data persisted remotely that requires asynchronous APIs for fetching and updating
When it comes to client state, Redux is a grate management tool for managing application’s state.
On the other side, to manage server state, we can use regular state management tools but they are not so great at working with async or server state. So, to resolve this, we use React Query. As described on their documentation, React query is a great tool for:
Caching... (possibly the hardest thing to do in programming)
Deduping multiple requests for the same data into a single request
Updating "out of date" data in the background
Knowing when data is "out of date"
Reflecting updates to data as quickly as possible
Performance optimizations like pagination and lazy loading data
Managing memory and garbage collection of server state
Memoizing query results with structural sharing
You can simply to think:
React Query = axios + cache logic
Redux can store synchronized data and asynchronized data
By the way, I use context manage synchronized state, React Query manage asynchronized state now.
I'm using axios.get() to call an api endpoint in one of my components. I need the ability to encapsulate this endpoint call so I can reuse this implementation by calling it from several different components.
What is a generally acceptable way to structure this type of implementation in a React project? For example, would it be generally acceptable to group related api calls into js files in a src/services directory at the same level as src/components?
It would be acceptable to create a utils or services directory and group related API calls. However it is important to remember that with async requests you need to consider the components calling the api service utils might un-mount. This might result in warnings or errors if not handled properly. A possible way to handle this might be to only execute callback functions if component is still mounted tracked via a state variable in a useEffect hook.
A more modern react approach might be to leverage hooks and react context for data handling. You could create a DataContext with a useReducer hook to fetch or push data for example.
(see https://reactjs.org/docs/context.html)
There are many way to do this.
Redux. It's old way is that you need to use redux style.
Hooks. Starts from React 16.8 version.
I will recommend to you use hooks. It's more useful and guarantee true way.
3 years ago i lived in Redux paradigm and every time write the monkey code thinking about consistent Redux store state.
Please try this one react-async package.
I'm currently making a REACT web app, and I've made heavy use of localStorage to keep track of data without having to make more api calls, i'll provide a quick explanation of what i'm doing and would like to know if it's a good practice or if there's a better way.
I am working on a blog app and need to have access to some data in other components (such as the username of the currently connected user.)
So each time I make an api call, and receive data that I know I will need in other components (especially if it's not a child component of the one receiving the data), I store it in the localstorage so I can access it easily.
Is making use of the local storage everytime I need it for convenience good ?
Do you have any guidelines regarding when to query data instead of relying on localStorage ?
Thanks for your answer.
Remember that localstorage is persistent data. So it should be used for data that is required when the user leaves your app and comes back to it again.
On the other hand, sharing data between components while your app is running should be done with other mechanisms, typically passing props from a parent component to child components. Also, you can use React context or Redux or similar APIs to store data that is required globally while your app is running.
I would say "it depends"
If you are not accessing data in localStorage way too often, data inside of it are not changing frequently. Then it is OK. (still you need to have fallback for any other storage, try safari in anonymous window there localStorage does not work, old mobiles have limits how much data can be stored etc. etc.)
Otherwise it would be better use other means of storing data locally. Like IndexedDB, WebSQL. You can use some lib for managing those like for indexDB dexie, idb or any other.
If you are using localStorage just to ease your work with react props drilling, then rather use React.context, flux, redux... or any other state managment lib.
I don't understand why we need Flux with React as React itself let's us maintain the state of the application. Every component has an initial state and the state can be changed by user actions or any other asynchronous JavaScript.
Why is React called as only a view library when it can let's us define state of the application and also update view whenever state changes. This is not what a view does....its what complete MVC does right?
For example: here is an Todo app build only with React and here is an Todo app build with Flux and React.
If we can build the Todo app with React only then why do we need Flux?
In theory you don't need flux.
In small applications you don't need flux for sure.
But what if your application consist of hundreds components? And one of your component is form. User populate this form and you send its content to server. And get response from server with new data.
And assume that this response data and data from form are necessary to other components.
Without flux:
You can move your data to root component and then distribute it down to all components. But if you need to distribute data from many other components too? This makes your application very complex.
with flux:
You move your data to stores, and all components which are interested about this data, can get it from there. You have better control on your application and source data.
I prefer redux (only one store and one source of truth)
edit:
Why is React called as a view library even if it can handle application state?
MVC is a software architectural pattern. It divides a given software application into three interconnected parts (models, views, controllers).
If we think about react and MVC it fit as View. But this is nothing wrong. It doesn't mean that you can use it only for views. It allows you to create normal applications.
But in other hand you can use it as view for other frameworks (for example you can use it with angular).
In other words it is very flexible library for many uses.
You don't NEED Flux the same you don't need MVC. They are both architectures and you can of course build something without using either.
Would you build a non-MVC app in 2016? Probably not, that doesn't mean that people didn't do it in the past.
Flux is awesome! But as most things in the tech industry is not always the right decision, things vary in a project requirement basis.
Probably the biggest selling point of Flux is that it tries to enforce the data flow in one direction, this means that you know for sure where the data is coming from. In a non-flux app the data for a component could be an own property, a property passed down the component tree, a local state variable, a state variable result of calling an API.
With Flux: "where does the data come from?". Answer: from the stores. Redux takes this further and only uses a single store.
Flux has been criticized because you need a lot of boilerplate code but again is a matter of tradeoffs.
At the end is always your call depending on your project needs.