I'm giving redux-orm a try and from what I can gather, redux-orm creates an object in store, whose key is the value specified via Model.name
, for every registered model.
Well,to create my "entities" reducer, I'm using combineReducers, passing in the reducers for all my entities, like this:
import { combineReducers } from 'redux';
import City from './cityReducer';
import Poi from './pointOfInterestReducer';
const entitiesReducer = combineReducers({
City,
Poi
});
export default entitiesReducer;
And finally this is how I create my rootReducer
, also using combineReducers
:
The problem is that,I think that, by using combineReducers
I'm duplicating the keys in my store like it's shown here:
Do you have any idea how I can avoid this, and have all my models be direct descendants of "entities"?
Something like entities>City
and not entities>City>City
Edit: cityReducer.js
import orm from './../../orm/orm';
import * as types from '../../actions/actionTypes';
const loadCities = (state, action) => {
// Create a Redux-ORM session from our entities "tables"
const session = orm.session(state);
// Get a reference to the correct version of model classes for this Session
const { City } = session;
const { cities } = action.payload;
// Clear out any existing models from state so that we can avoid
// conflicts from the new data coming in if data is reloaded
City.all().toModelArray().forEach(city => city.delete());
// Immutably update the session state as we insert items
cities.forEach(city => City.parse(city));
return session.state;
};
const updateCity = (state, payload) => {
const { id, newItemAttributes } = payload;
const session = orm.session(state);
const { City } = session;
if (City.hasId(id)) {
const modelInstance = City.withId(id);
modelInstance.update(newItemAttributes);
}
return session.state;
};
const deleteCity = (state, payload) => {
const { id } = payload;
const session = orm.session(state);
const { City } = session;
if (City.hasId(id)) {
const modelInstance = City.withId(id);
// The session will immutably update its state reference
modelInstance.delete();
}
return session.state;
};
const createCity = (state, payload) => {
const { city } = payload;
const session = orm.session(state);
const { City } = session;
City.parse(city);
return session.state;
};
const citiesReducer = (dbState, action) => {
const session = orm.session(dbState);
switch (action.type) {
case types.LOAD_CITIES_SUCCESS: return loadCities(dbState, action);
case types.CREATE_CITY_SUCCESS: return createCity(dbState, action);
case types.UPDATE_CITY_SUCCESS: return updateCity(dbState, action);
case types.DELETE_CITY_SUCCESS: return deleteCity(dbState, action);
default: return session.state;
}
};
export default citiesReducer;
There's two ways you can use Redux-ORM to define its "tables" structure, and write reducer logic to use those tables. I gave examples of both approaches in my blog posts Practical Redux, Part 1: Redux-ORM Basics, Practical Redux, Part 2: Redux-ORM Concepts and Techniques, and Practical Redux, Part 5: Loading and Displaying Data. (Note that those posts cover use of Redux-ORM 0.8, and version 0.9 has some API changes. I listed those changes in Practical Redux, Part 9.)
The first approach is to write your reducer logic attached to your model classes, and use the Redux-ORM
ORM
instance to generate a reducer that creates the "tables" and manages them for you. Per the example on the front of the Redux-ORM repo:The other approach is to write your own function that creates the initial state, and possibly other functions that handle the updating:
In other words, don't define the separate per-model-type "tables" yourself. Let Redux-ORM define those, either automatically in its own reducer, or by using it to generate the initial state for your entities reducer.