Redux Structure Advice - reactjs

I've built a few React Native apps with Redux and I've traditionally modeled my state after the views/ui. I've come to realize that this isn't the best way to organize Redux state.
Through some recent research, I know now that it's best practice to not store duplicate data in different reducers, as updating them can become tedious. It's better to store data in objects with the keys being the id and the value being the data object itself.
This makes sense for data that will be the same on every screen/page, but what if your app uses the data differently on different screens?
For example:
I have a list of products on a home screen and a list of products on a category screen. Both have pagination and are looking at different subsets of the product data. I could use a selector method here and only select products belonging to the specific category on the category screen, but how would that work with keeping track of pagination data for each one?
If I scroll down on the home screen and load a bunch of product data, then switch to the category screen, I'll have more data already loaded.
Any advice is appreciated, thanks!

You should normalize your data (https://github.com/paularmstrong/normalizr) so you can have your redux state like:
{
home: [...list_of_id_products],
category: [...list_of_id_products],
data: [actual_array_of_objects]
}
then you can have separated lists, all linked to the same set of data

Related

How to manage states of a shared component where we want to retain the states based on the place the component is being used?

For example: let's say we have a table component used on multiple pages or in a page multiple times. Now, we want to maintain the selected items from the table for each table and highlight them.
So, currently, I am using an object to store the selected items based on the place it's being used:
{
place1: {selectedItemId1: selectedItem1, selectedItemId2: selectedItem2},
place2: {selectedItemId1: selectedItem1, selectedItemId2: selectedItem2},
place3: {selectedItemId1: selectedItem1, selectedItemId2: selectedItem2}
}
Please let me know if you've any other better solution.

Structuring the Firestore: Should I make another collection to store the changes that were made?

I am using Reactjs and Firestore.
I have this collection of products:
The colorMap is a map then below it are the different colors and their quanty.
Now, I want to create a list or a history whenever a product is added and whenever the quantity in those colors was added more of it.
Should I add another collection that will store when a product is added or whenever quantities are added in the color? I'm also thinking of adding a createdDate
Or there any other way I could do this? As much as possible, I won't be using any cloud functions.
A common way to keep the history of each document is by creating a subcollection under that document (say history) and writing a new document with either the complete, old document data there for every update you perform, or a new document with just the old values of the fields that were modified.
While it is convenient to do this from Cloud Functions, as they already get both the previous and the new data for each document write, you can accomplish the same from client-side code too.

Can you update firestore query dynamically based on router location?

So basically, I have a simple React app connected to Firebase that lists different types of food from firestore collections.
Example:
I have a few categories. The default one is "All" that displays top 8 popular dishes from all other available categories and this part is easy but I want an user to be able to click on other category and update my query.
Category is actually a NavLink that updates location on click so: if user click on "Pizza" category the url looks like this localhost:3000/Pizza if he clicks on Salad it is localhost:3000/Salad etc.
I have a "Wall" component that is a section and it displays those items from firestore.
My query ref in this wall component look like this: const foodRef = db.collection("food").doc("all").collection("items");
But I want to set .doc dynamically and make query on every update so I changed the query to something like that:
const location = useLocation();
const foodRef = db.collection("food").doc('${location.pathname}').collection("items");
And when user click on different Card (NavLink) url updates but query does not.
I know it is a bad solution but I actually have no idea how to do that.
I have read about Recursive Paths in react router but I do not know if it is what I am looking for.
If you know how to approach that please let me know.
Thanks for your time.
Firestore does not support wildcards or replacements in queries and Query objects are fully immutable (they can't be changed). You have to know the names of the documents and collections ahead of time to build a query. If you want to change some part of a query, you have to rebuild a whole new query object every time, and run the query again to get a new set results.

How to design shopping cart data with Firestore?

I use Firestore as my back-end. I have designed my data for the shopping cart like this:
cart--
cartid--
product--
id: 'dsdasd',
title: 'New Dress',
price: 10,
images: 'https://someurl/image.jpg
totalPrice: 50,
amount: 5
But I am not sure to use it. I'd like to hear some suggestions for this situation. I built it in React.js. How can I design my shopping cart data with Firestore? What should I use Firebase or Firestore?
I'd personally use Firestore, but it also depends on your needs and your app's requirements. You can read more about differences between the Realtime DB and Firestore here.
Talking about your data model, I'm not sure about your actual implementation (it's not clear from the question), but you may need two different collections: products and carts.
Every cart document will have a field (array/object) with all the products IDs in that cart. This way you can achieve data consistency, fetching product data from the actual product document every time you need it (for example displaying the cart).
The totalPricefield in the cart is probably unnecessary and leads to data inconsistency, because you need to update it when products in the cart change. It might be better to display the total price in the front end with a simple sum.

Passing data between components using typescript, react, react-router

I'm creating a large single page app with typescript (v1.8.10), react (v15.0.2), and react-router (v2.4.0) and I'm trying to find the best way to have data pass between components in the following type of scenario. I've seen other questions that are somewhat similar, but not quite the same especially when considering the type safety that TypeScript provides and I'd like to take advantage of.
Lets say I have a car viewing application with the following components: ComparisonComponent, DetailsComponent, and SelectComponent.
The DetailsComponent will show details of a car model and has a "select car" button which will bring up the SelectComponent. Once the user selects a car in the SelectComponent, the details of that car should be displayed in the DetailsComponent.
The ComparisonComponent will compare two car models and has 2 separate "select car" buttons (eg. button A and button B). When the user clicks button A, the SelectComponent should be displayed. Once the user selects a car in the SelectComponent, Car A should be displayed in the ComparisonComponent. Similarly if user hits button B, selects a car in SelectComponent, then Car B should be displayed in ComparisonComponent.
So, I am envisioning having the following routes:
"/details" -> DetailsComponent
"/details/select" -> SelectComponent
"/compare" -> ComparisonComponent
"/compare/select" -> SelectComponent
So, my questions are what is the proper way using react and react-router to have the SelectComponent pass back the selected car? Since the SelectComponent should be shared between the other components, once the user is done selecting a car, how does the CompareComponent know whether it was Car A or Car B that was selected? Since the SelectComponent is not a child of either DetailsComponent or CompareComponent, I don't think I can pass state from DetailsComponent or CompareComponent via props. So, how would I pass data between those different routes using react router?
What would be the proper flux way of handling this type of scenario? Would I create a details store and a compare store to keep track of the component specific data as the user navigates? It seems like that would lead to keeping a lot of UI specific data in stores, when that UI specific data is no longer used. It seems to me that it would waste a lot of memory especially for a large single page app that will end up having 100+ routes. How do I keep from showing stale data if the user exits and reenters either the DetailsComponent or the CompareComponent?
Thanks for any help that you guys can provide.

Resources