I am relatively new to React and Redux after spending a lot of time in the .net mvc and knockoutjs world. What I am having trouble understanding is how the store is used and how props are passed down between parent and child components.
My first question: if an array of values get sent down from parent to children components via props, do these components do a deep copy and create their own version of this array? If we have a rather large array of values that we want multiple children to have access to, and we send it as props, are we unnecessarily creating extra data or are they just simply referencing the same array?
I'm not sure exactly how the store is used, but could it be used to help the scenario above? If we have some values like a larger array that we want accessed by multiple component children, they could pull them from this globally accessible store?
I would appreciate if somebody could help me wrap my head around these concepts. In my scenario I'm working on we have a table of 30 students each of which gets sent an array of data to help fill in some rows. What I'm afraid we're doing though is giving each student a large amount of data that they don't need if they could pull from the parent or this global store.
<StudentTable
onSelectAllStudents={this.props.handleSelectAllStudents}
handleLoadStudentResponses={this.props.handleLoadStudentResponses}
structures={this.props.structures}
lessons={this.props.lessons}
activities={this.props.activities}
students={this.props.students} />
They are creating a table, where each row is a student. The table contains a large amount of data (which is a whole other problem) however what essentially we are doing is for each student we are showing whether they completed a particular activity or not. As you can see in the screenshot they build out a rather complex table. In the StudentTable they loop through students and create a Student component for each row which gets sent in the list of activities so that in the table they can color in a cell based on if the activity is published or not. My main fear was that with each Student component getting the list of activities it was adding a ton of data to memory as opposed to those numerous Student components just referencing some parent array.
Based on the syntax I've seen, children receive a pointer. Not a new object. Regarding your question about giving 30 students the entire array, you're not approaching data passing correctly. Show us a code snippet and I'll be able to comment more.
Also, redux is not helpful. It can be used, but it's overkill and adds needless complexity. Components with a child-parent relationship can very easily be handled with normal React prop passing. Redux is the go-to option if the components do not have any direct relation.
edit: When referencing elements in an obj, primitives are copied and objects are pointed.
const obj = {arrayObject: [], primitiveBoolean: true}
const primitive = obj.primitiveBoolean
const array = obj.arrayObject
primitive = false
console.log(obj.primitiveBoolean); //still true
array.push(10)
console.log(obj.arrayObject); // [10] push changed object's array
Related
I need to keep a large amount of items in state.
Consider
this.setState(oldState => ({
items: [...oldState.items ...newItems]
}))
It creates a new array and copies all the items here, which is slow.
The performant way of adding items would be pushing them on to the old list, but this requires mutating state directly, which may or may not lead to weird bugs.
Lately I moved onto using state like this:
this.setState({
["items"+num]: newItems
})
For example, if num==8, then we will create a new key in the dictionary "items8" and set its value to be equal to the array of new items.
I assume in this case React will mutate state to add a new key-value pair (as opposed to creating a new state object). Also, I assume React will pass a reference to the original array, rather than duplicating the array.
Is this a performant way of using React state with a large collection of items? For the purpose of this question, let's assume I am not rendering anything to the DOM.
Edit: I was asked for more context in the comments. I'm working on an open source infinite scroll implementation. It's not for any specific purpose. My data is images and my metadata contains only urls for the image and image thumbnail. However, someone who uses my infinite scroll implementation might use it for a different purpose, like blog posts, or videos, or any other types of items. The general idea is that as the user scrolls down, we fetch metadata for more items, and we want to add that metadata to state. So if someone scrolls very fast, they might cause many state changes per second, and I want those state changes to be fast even if there are many items in state.
I have a large form consisting of 30-40 fields.
The form is logically and visually divided into parts. For example: "address details" "credit card details". I would like to divide it into multiple React components.
In my form, changes by user in some parts often cause other parts to change. Some changes are:
Resetting certain parts of the form.
Auto-filling certain parts of the form (e.g. for certain credit card we automatically offer address saved from past transactions)
rerun validity check of different parts (e.g. we only ship to this address for purchases of 100$ or more)
As far as I understand in React parent should not call functions on children (through ref) but rather declare state, which flows to the children through props. However, all of the changes mentioned are just initial state, and can be immediately overridden by user input.
My options as far as I understand are:
imperatively pass state to children. This could be done through ref, or through a prop "initial/override value". Either way I'm manually passing state, rather than having one single source of truth.
Make my children forms "dumb" and receive all form values from parent. This seems impractical (as far as I can tell) because I would have to pass every single input value up and receive all of them as props.
Similar to 2, store the state in Redux. I would still have to store every single value of the form in the store, which is cumbersome It also seems to be discouraged by the React community.
Give up on dividing the form into sub-components. I only have one source of truth (component state) Honestly that currently seems like the best solution.
How would you do it?
Thanks for your time.
I have a long length array of numbers in firestore. This array is also just one of the property of my object model.
3 of my components on different pages need this array;
1st component doesn't need this array but needs another properties of my object model. So i have to fetch it from firestore without any other reason.
-2nd component needs this array to reduce its values and display result on the page.
-3rd component needs to display whole array data.
What is the optimized way to store and exchange these data between those components to avoid any memory leaks or unnecesary firestore calls (free calls are very limited and it makes my web app much more slower)??
I tried to assign this object to my service but hence it is an observable i had to subscribe to it everytime a component needs this data.
Need your help.
Thanks in advance.
I would stay with using the obervables, so you can make sure that the state within your forms stays in sync with your array data. If you start moving copies of your array around you would have to establish additional state management like Ngrx etc. to achieve this. Also Firestore has a caching feature built in, so it's not always reading data from the server.
Cheers,
Lars
If in my React app, utilizing Redux and redux-thunk, my store has an array of relatively lightweight/denormalized items that is used in a listing of said items (paginated in the API), but then I also have an edit/add option for each (which is the same item as in the listing array but with many additional fields, not de-normalized, etc.), I don't know which of the following is the best approach for storing in my store:
Maintain one array of items in my store, which contains all necessary data (normalized, and therefore each contains a relatively deep object graph). Editing simply requires finding it in the store, making the changes, and slicing back into the state.items array.
Maintain an array of minimalist items for the item listing, while also having a root state.currentItem object.
Maintain an array of minimalist items for the item listing, while resetting the array to contain only one item (containing all necessary data for editing). This avoids needing to create another reducer which may or may not be a good thing.
Because of the data-intensiveness of the actual listing item object, I have to go with option 2/3, but now I've got redundant data in two places that conceivably won't be in sync (although practically speaking, in my app, because of paging/sorting I must necessarily re-poll for latest data from the API upon returning back to the listing) or an array of items that can contain items in two different object formats.
Both feel dirty, which leads me to believe I'm missing something obvious that redux is already equipped to handle. Suggestions? Additional options?
Can the user update multiple items at the same time? Redux has 3 important principles to respect. One of them is the single source of truth, which means all valid/true data must come from one place (store here) and every data element is stored exactly once. Having multiple time the same items in the store is bad, mainly because of sync problems like you said. Also having deep objects is not a good approach, you should keep your state flat. Since you're using react with redux, you have access to state, the app state with redux and the component state with react. The most common pattern with this kind of problem is to create a copy of the object that you are editing in the component state. If the user cancels the editing, it will be easy to revert it. If the user stops editing the item without saving, you app state won't be affected. Also, you will avoid polluting your app state with wrong or duplicated data. Let's say that in your list when a user clicks on an item, the item transform to a text input. The list item will be base on the redux store item and the text input will be base on a copy of the same item. This also applies to new objects. You can also validate your item before adding/updating it. Keep in mind that the most important part is to keep your store clean because you will base you displayed items on that, so fetching new items won't affect your list. Doing this will also help you updating the item in the store because you will only have to replace it when dispatching a save action.
What's the best way to handle a case where multiple components are using one store (which is populated by API calls in an action creator), but each component may need to access different sets of data without effecting the other. I.e.: two table components display data from the WidgetStore; one table wants all widgets, the other only displays widgets whose name contains "foo" (this would be based on user input). The table being queried via the API has tens of thousands of widgets, so loading them all into the store and filtering from the store isn't practical. Is there a Flux architecture (like Redux) that already has a way of handling this type of thing?
The simplest way is to just create a parent component and selectively hand off data, using a pluck or selector function, to each of the children.
For the more general answer for yourself going forward... if you follow something along the lines like redux there is already proven patterns which will help you understand passing complex data down.