I am used to computed properties in Ember Object Model. It's a convenient way to specify computed properties that depend on other properties.
Say fullName
depends on firstName
and lastName
, I can setup computed properties as a function computeProperties
and call computeProperties
each time I make a change.
Example:
function computeFullName(state) {
const fullName = state.get('firstName') + state.get('lastName');
const nextState = state.set('fullName', fullName);
return nextState;
}
function computeProperties(state) {
const nextState = computeFullName(state);
return nextState;
}
// store action handler
[handleActionX](state) {
let nextState = state.set('firstName', 'John');
nextState = state.set('lastName', 'Doe');
nextState = computeProperties(nextState);
return nextState;
}
Is there a way to automatically setup computed properties so that I don't have to call extra functions each time. In Redux or in ImmutableJS.
Redux author here!
Using reselect as suggested by WildService is the way to go. I think we won't include this in core because reselect does its job well and we're fine with it being a separate library.
I wanted to note a couple of things:
Even with reselect, you don't want to compute data inside your reducer. Selectors should operate on the state managed by reducers. In other words, selectors are the step between your Redux store state and your components—they are not inside your reducers. It is essential you keep Redux state normalized so it's easy to update.
We actually encourage you to define selectors alongside the relevant reducers, so that when you change the state shape, you don't have to change your components—they would be using the selectors instead. You can see an example of this in the Redux folder of Flux Comparison
We have a documentation page introducing reselect and describing how to use it for computing derived data. Check it out.
Check out reselect. Composable pure functions for efficiently computing derived data from stores. Afaik there are plans to roll reselect's selectors into Redux core at some stage if they prove popular. There's an example for usage with ImmutableJS at the bottom of the readme too.
To create computed properties you can use the standalone observable library mobservable.
var user = mobservable.props({
firstName: 'John',
lastName: 'Doe',
fullName: function() {
return this.firstName + this.lastName
}
});
var nameViewer = mobservable.ObservingComponent(React.createClass({
render: function() {
return (<span>{user.fullName}</span>)
}
});
That should be the gist of it, now any change to user.firstName or lastName will rerender your nameViewer component. You can further combine this with flux implementations like redux to change the data, and push the user itself through your component tree. But note that the user object itself is not immutable (in that case it wouldn't be observable after all ;-)) Also see this trivial and slightly more interesting fiddles for some examples.
What about something like this?
export const getWidgetsWithComputedProps = widgets => {
return widgets.map(w => getWidgetWithComputedProps(w));
};
export const selectWidgetType = widget => {
switch (widget.type) {
case 'line':
return 'time-series';
case 'pie':
case 'bar':
return 'cross-sectional';
default:
console.warn('Back up: that type of widget does not exist!', widget.type);
return null;
}
};
export const getWidgetWithComputedProps = createSelector(
widget => widget,
selectWidgetType,
(widget, _type) => {
return {...widget, _type}
}
);