I am witnessing some magic over here.
First of all, this is a pretty common question and believe me I've done my research, so please before you mark this as duplicate, first hear me out.
The difference in performance between arrays and objects has been brilliantly explained in this SO answer and I've applied it to my React Native application with the hopes that it will improve my performance by about 300%. But the results are a huge, disappointing surprise.
I changed my data structure from an array of objects...
let poems = [ obj1, obj2, ..., obj64]
to an object with keys as object id
s and values as the whole objects themselves
let poems = { "obj1_id": obj1, "obj2_id": obj2, ...}
Now if I want to access an object, instead of looping through the array and testing for quality of say id
attribute, I can instead just do this: poems[obj1_id]
and this will be far more efficient (speed wise).
No matter how I think about it, I don't see any reason why this should not be the case. So now I want to share my source code (React Native) because I suspect that the problem might be with the way I'm implementing.
Here is my data
poems.json:
{
"Family": {
"1": {
"id": "1",
"category": "Family",
"favorite": false,
"body": "Poem 1"
},
.
.
.
"64": {
"id": "64",
"category": "Family",
"favorite": false,
"body": "Poem 64"
}
}
}
This is my reducer: poemReducer.js
import all_poems from '../data/poems_obj.json';
const initialPoems = {
allPoems: all_poems,
currentPoems: {},
favoritePoems: {}
};
export default poems = (state = initialPoems, action = {}) => {
switch (action.type) {
case SET_POEMS:
return state;
case SET_CURRENT_POEMS:
return {
...state,
currentPoems: state.allPoems[action.name]
};
case TOGGLE_FAVORITE:
let currentPoems = state.currentPoems;
let favoritePoems = state.favoritePoems;
let poem = currentPoems[action.id];
poem.favorite = !poem.favorite;
if (poem.favorite) {
favoritePoems[poem.id] = poem;
} else {
delete favoritePoems[poem.id]
}
return { ...state, currentPoems, favoritePoems };
default: return state;
}
}
Believe it or not, when I click on the favorite button to toggle a poem's favorite boolean value, it takes approximately 9s
. Not 9ms, 9 frigging SECONDS in an object with a size of only 64 objects.
Here is how I dispatch the actions:
export const toggleFavorite = (id) => {
return {
type: TOGGLE_FAVORITE,
id
};
}
Am I doing something wrong? Is there something I don't get about the overall idea.
Any insights will be very much appreciated.
EDIT
Sorry if this wasted anybody's time. I realize I was making a mistake in an entirely different part of my application. In the React Native componenent of my application responsible for rendering the poems, I was doing something like this:
First I got the poems from redux:
mapStateToProps = (state) => { poems: state.poems.currentPoems }
Since the poems exist in redux as objects, these poems come in the is format:
{
"1": {
"id": "1",
"category": "Family",
"favorite": false,
"body": "Poem 1"
},
.
.
.
"64": {
"id": "64",
"category": "Family",
"favorite": false,
"body": "Poem 64"
}
}
I am rendering this in a FlatList
component in React Native so I need this data to be an array of objects. So to convert the object into an array of objects, I do this just before the return
statement in my render()
method:
const { poems } = this.props; // grab from redux, via mapStateToProps function
const poemsArr = Object.keys(poems).map(key => peoms[key]); // change into array of objects
then I proceed to pass this poemsArr
as value to the data
attribute of my Flatlist component.
<FlatList
data={poemsArr}
renderItem={this.renderItem}
/>
Somehow this slowed down my application big time.
Now the change I made that got my code to be working properly was that instead of converting my object to array of objects inside the render()
method, I did it directly in the mapStateToProps()
method:
mapStateToProps = (state) => { poems: Object.keys(currentPoems).map(key => currentPoems[key]) }
That solved my problem. I don't have a good explanation for why it works yet. That's my assignment for now.
I'm sorry if this wasted anybody's time. Thanks for your contributions. They really helped me.
P.S.: I did a lot of modifications on my original source code before posting it here to keep it general and simple. There might be some syntax errors as I am only a beginner JavaScript developer. Thanks