Reselect - does it ever make sense to create a memorized selector which is just used to get part of the state? - redux

I have a normal selector which is just used to get part of the state:
export const getAllPosts = state => {
return state.posts;
};
If I use the reselect to wrap the selector:
import { createSelector } from 'reselect';
export const allPosts = createSelector(
getAllPosts,
(posts) => posts
);
Does it make any sense such as improving performance ? In my opinion, the wrapper is unnecessary.

No, it does not make sense to create a memoized selector just to get part of the state tree.
The reason is that connect will do it’s own shallow equality check for each prop passed in from mapStateToProps. If the prop returned by the selector passes that shallow equality check, along with the other props, then render will not be called unnecessarily. If the selector simply returned a part of the state tree and that part of the state tree had not been modified then a shallow equality check will be sufficient.
However, If the selector is computed from the results of other selectors then using createSelector is a good choice. Firstly, it provides a nice syntax for composing selectors. Secondly, if the computation of combining the selectors is potentially expensive you will get a performance benifit. Thirdly, if the selector was to return a new, but equivelent, object or array then the shallow equality check provided by connect would not be sufficient. In that case the memoization that createSelector provides would ensure that the same object or array instance was returned if the inputs had not changed and then the shallow equality check would be sufficient to avoid costly re-renders.
So for just exposing parts of the state tree createSelector doesn’t add anything.
For nearly all selectors that are computed from multiple parts of the state tree createSelector begins to add value. The amount of value that it adds varies based on the selector from just being easier to read up to ensuring you don’t re render the component tree unnecessarily.

In your case it does not make sense cause you just return the same reference from the store which is always shallow equal to itself (or it's previous state) unless you modify it.
If you imagine a different scenario for example a scenario where you store your entities in an object instead of an array in the store but you want to return an array to your Component then you need to derive data:
export const selectAllPosts = createSelector(
getAllPostsFromStore, // returns { 1: {...}, 2: {...} }
(allPosts) => Object.keys(allPosts).map(key => allPosts[key])
);
Now your selector turned into a performance boost cause it only computes the derived data when something in the store changes.
So my rule of thumb is: If you don't derive data, you don't need to memoize it.

No, that provides no real benefit.
What I've found is that my first-level selectors are simply plain functions, and any selectors that go deeper than that need to be memoized:
// assume state is: {first : {second {} } }
const selectFirst = state => state.first;
const selectSecond = createSelector(
selectFirst,
first => first.second
);

Related

NgRx reducer function with condition

I have a side effect that detects the browser language and dispatches a browserLanguageSupported action if it is a language that my application can handle.
Now I have following reducer function that only updates the states preferredLanguage property in case it is not defined already. This is important because there are other actions that update this state property and I do not want a late browserLanguageSupported action to overwrite such a state update.
export interface State {
preferredLanguage: AppLanguage | undefined;
rehydrationComplete: boolean;
}
export const initialState: State = {
preferredLanguage: undefined,
rehydrationComplete: false
};
export const reducer = createReducer(
initialState,
on(LanguageActions.browserLanguageSupported, (state, {browserLanguage}) => {
if (!state.preferredLanguage) {
return {...state, preferredLanguage: browserLanguage};
}
return state;
})
);
Now for my question: Is it good practice to have such a condition in a reducer operator? The function itself is still pure. But I am not sure if it is good design or if I should solve it differently, lets say by adding state slice selection in the side effect that dispatches this action.
Btw. the reason I am not setting it directly in the initial state is because I get the browser language from an angular service and I am not sure if it is even possible to set initial feature state from service injection?
Best regards,
Pascal
I would to this the same way, so you get a 👍 from me.
Adding a slice of the state into the effect just adds needless complexity.
The reducer contains the state, and it's OK to add logic to see if state needs to be updated or not.
Also, let's say you need to add this logic into another action/effect.
Having it in the reducer makes it easier to reuse if it's needed. Otherwise you end up with duplicate logic.
As long as the rejection (or mutation) of the data is irrelevant to the chain of actions & effects, this is absolutely valid.
However, it's worth noting that if the action in question triggers an effect which triggers an action, the triggered action will not know whether the data was rejected (or mutated) without checking the state—which is exactly what this pattern is attempting to avoid.
So, if you wanted to be able react to that rejection (or mutation), you would want to handle this in the effect. But, if you would proceed in exactly the same manner regardless of the result, then it belongs reducer.

Treating single and multiple elements the same way ("transparent" map operator)

I'm working on a programming language that is supposed to be easy, intuitive, and succinct (yeah, I know, I'm the first person to ever come up with that goal ;-) ).
One of the features that I am considering for simplifying the use of container types is to make the methods of the container's element type available on the container type itself, basically as a shortcut for invoking a map(...) method. The idea is that working with many elements should not be different from working with a single element: I can apply add(5) to a single number or to a whole list of numbers, and I shouldn't have to write slightly different code for the "one" versus the "many" scenario.
For example (Java pseudo-code):
import static java.math.BigInteger.*; // ZERO, ONE, ...
...
// NOTE: BigInteger has an add(BigInteger) method
Stream<BigInteger> numbers = Stream.of(ZERO, ONE, TWO, TEN);
Stream<BigInteger> one2Three11 = numbers.add(ONE); // = 1, 2, 3, 11
// this would be equivalent to: numbers.map(ONE::add)
As far as I can tell, the concept would not only apply to "container" types (streams, lists, sets...), but more generally to all functor-like types that have a map method (e.g., optionals, state monads, etc.).
The implementation approach would probably be more along the lines of syntactic sugar offered by the compiler rather than by manipulating the actual types (Stream<BigInteger> obviously does not extend BigInteger, and even if it did the "map-add" method would have to return a Stream<BigInteger> instead of an Integer, which would be incompatible with most languages' inheritance rules).
I have two questions regarding such a proposed feature:
(1) What are the known caveats with offering such a feature? Method name collisions between the container type and the element type are one problem that comes to mind (e.g., when I call add on a List<BigInteger> do I want to add an element to the list or do I want to add a number to all elements of the list? The argument type should clarify this, but it's something that could get tricky)
(2) Are there any existing languages that offer such a feature, and if so, how is this implemented under the hood? I did some research, and while pretty much every modern language has something like a map operator, I could not find any languages where the one-versus-many distinction would be completely transparent (which leads me to believe that there is some technical difficulty that I'm overlooking here)
NOTE: I am looking at this in a purely functional context that does not support mutable data (not sure if that matters for answering these questions)
Do you come from an object-oriented background? That's my guess because you're thinking of map as a method belonging to each different "type" as opposed to thinking about various things that are of the type functor.
Compare how TypeScript would handle this if map were a property of each individual functor:
declare someOption: Option<number>
someOption.map(val => val * 2) // Option<number>
declare someEither: Either<string, number>
someEither.map(val => val * 2) // Either<string,number>
someEither.mapLeft(string => 'ERROR') // Either<'ERROR', number>
You could also create a constant representing each individual functor instance (option, array, identity, either, async/Promise/Task, etc.), where these constants have map as a method. Then have a standalone map method that takes one of those "functor constant"s, the mapping function, and the starting value, and returns the new wrapped value:
const option: Functor = {
map: <A, B>(f: (a:A) => B) => (o:Option<A>) => Option<B>
}
declare const someOption: Option<number>
map(option)(val => val * 2)(someOption) // Option<number>
declare const either: Functor = {
map: <E, A, B>(f: (a:A) => B) => (e:Either<E, A>) => Either<E, B>
}
declare const either: Either<string,number>
map(either)(val => val * 2)(someEither)
Essentially, you have a functor "map" that uses the first parameter to identify which type you're going to be mapping, and then you pass in the data and the mapping function.
However, with proper functional languages like Haskell, you don't have to pass in that "functor constant" because the language will apply it for you. Haskell does this. I'm not fluent enough in Haskell to write you the examples, unfortunately. But that's a really nice benefit that means even less boilerplate. It also allows you to write a lot of your code in what is "point free" style, so refactoring becomes much easier if you make your language so you don't have to manually specify the type being used in order to take advantage of map/chain/bind/etc.
Consider you initially write your code that makes a bunch of API calls over HTTP. So you use a hypothetical async monad. If your language is smart enough to know which type is being used, you could have some code like
import { map as asyncMap }
declare const apiCall: Async<number>
asyncMap(n => n*2)(apiCall) // Async<number>
Now you change your API so it's reading a file and you make it synchronous instead:
import { map as syncMap }
declare const apiCall: Sync<number>
syncMap(n => n*2)(apiCall)
Look how you have to change multiple pieces of the code. Now imagine you have hundreds of files and tens of thousands of lines of code.
With a point-free style, you could do
import { map } from 'functor'
declare const apiCall: Async<number>
map(n => n*2)(apiCall)
and refactor to
import { map } from 'functor'
declare const apiCall: Sync<number>
map(n => n*2)(apiCall)
If you had a centralized location of your API calls, that would be the only place you're changing anything. Everything else is smart enough to recognize which functor you're using and apply map correctly.
As far as your concerns about name collisions, that's a concern that will exist no matter your language or design. But in functional programming, add would be a combinator that is your mapping function passed into your fmap (Haskell term) / map(lots of imperative/OO languages' term). The function you use to add a new element to the tail end of an array/list might be called snoc ("cons" from "construct" spelled backwards, where cons prepends an element to your array; snoc appends). You could also call it push or append.
As far as your one-vs-many issue, these are not the same type. One is a list/array type, and the other is an identity type. The underlying code treating them would be different as they are different functors (one contains a single element, while one contains multiple elements.
I suppose you could create a language that disallows single elements by automatically wrapping them as a single-element lists and then just uses the list map. But this seems like a lot of work to make two things that are very different look the same.
Instead, the approach where you wrap single elements to be identity and multiple elements to be a list/array, and then array and identity have their own under-the-hood handlers for the functor method map probably would be better.

Modify selector in redux saga without mutating state

When using a selector, I thought that I could do whatever I wanted with the variable without modifying the state, so I was surprised that the state became mutated.
So if this is wrong (in a redux saga):
const filters = yield select(state => state.filters.filters);
filters.terms['helloo'] = "mutated";
//send data with request
yield put(requestData(filters)
How come that first line is a direct reference to the state?
Anyway, if I try using Object.assign, it also mutates state:
const filters = Object.assign({}, yield select(state => state.filters.filters));
filters.terms['helloo'] = "mutated";
How do I create a selection that is a copy of the state?
There's truly no "magic" involved here. Redux's getState() is literally just return state, and both hand-written selectors and Reselect return whatever you have written the functions to return. So, in that example, filters is the actual object reference that's nested inside the store state, because that's what your function returned.
Per the Redux docs page on "Immutable Update Patterns", you need to copy all levels of nesting that you want to update. In your example, you're making a copy of filters, but not filters.terms, so terms is also still the original object that's in the store. You would need to make a copy of that as well, and modify the copy.

Result functions of type x => x are unnecessary?

There might be a gap in my understanding of how Reselect works.
If I understand it correctly the code beneath:
const getTemplates = (state) => state.templates.templates;
export const getTemplatesSelector = createSelector(
[getTemplates],
templates => templates
);
could just as well (or better), without loosing anything, be written as:
export const getTemplatesSelector = (state) => state.templates.templates;
The reason for this, if I understand it correctly, is that Reselect checks it's first argument and if it receives the exact same object as before it returns a cached output. It does not check for value equality.
Reselect will only run templates => templates when getTemplates returns a new object, that is when state.templates.templates references a new object.
The input in this case will be exactly the same as the input so no caching functionality is gained by using Reselect.
One can only gain performance from Reselect's caching-functionality when the function (in this case templates => templates) itself returns a new object, for example via .filter or .map or something similar. In this case though the object returned is the same, no changes are made and thus we gain nothing by Reselect's memoization.
Is there anything wrong with what I have written?
I mainly want to make sure that I correctly understand how Reselect works.
-- Edits --
I forgot to mention that what I wrote assumes that the object state.templates.templates immutably that is without mutation.
Yes, in your case reselect won't bring any benefit, since getTemplates is evaluated on each call.
The 2 most important scenarios where reselect shines are:
stabilizing the output of a selector when result function returns a new object (which you mentioned)
improving selector's performance when result function is computationally expensive

Do Redux selectors cause unnecessary component renders?

From what I've understood from Dan Abramov's egghead video 'javascript-redux-colocating-selectors-with-reducers' and some of his tweets, it is a good practice to use a selector to map the state to a prop and remove this logic from the Component and placing it in the Reducer (where the state is managed).
Although this makes all the sense, it also causes my component to render everytime a new state is added to the store, even when only a non related property of the state object was changed. Is there a way to overcome this without using reselectors, which might be a bit overkill for the simpler cases?
As you may know, mapStateToProps is called every time your store is updated.
Whether the component will re-render depends on what mapStateToProps returns. (Actually, it depends on the combined props object returned by mapStateToProps and mapDispatchToProps.)
React Redux (the library that provides the connect function) makes a shallow equality check on the returned object and the last returned object. If the equality check succeeds (i.e. the previously returned object is determined to be equal to the next returned object), the component will not re-render. If the check fails, the component will re-render.
For example, let's say you always return the following object from mapStateToProps:
{
items: [],
}
This object will never be equal to itself ([] === [] returns false because they're different arrays). The equality check will thus fail and the component will re-render.
However, React Redux performs a more complex equality check that that (the implementation of its shallowEqual function can be found here).
For example, even though { a: 'b' } === { a: 'b'} returns false (they're different objects), shallowEqual will pass them off as equal. This is because shallowEqual will compare each key of the returned object with each key of the previously returned object, but only one level deep. More details can be found in the implementation I linked to above.
In summary, if you don't want your component to re-render, you'll need to make sure that the equality check succeeds.
You can:
Save the returned object into the state using a reducer
Cache the result using Reselect
Implement shouldComponentUpdate in the component by hand
These suggestions come straight from Redux's FAQ page: https://redux.js.org/docs/faq/ReactRedux.html#react-rendering-too-often
You can also make sure your mapStateToProps function returns objects that are considered equal by shallowEqual (e.g. objects without arrays, and only one level deep).
For simplicity, I would opt for Reselect.
The short answer is: No it is not.
But there is common mistake that causes unnecessary renders of components when you're using selectors. You should always make sure to define your selector once. So what does it mean?
When you are using connect method, you can pass mapStateToProps method as an argument. Object returned by this method will be passed as props to your component and if you define your selector inside this object it will be redefined each time your component receives a prop. Here is an example for that:
Defining your selector like this could cause your component to render unnecessarily. This is because each time you pass a prop to your component you're basically redefining getSettings method.
#connect(state => ({
getSettings: ()=>'sample output',
}))
class Sample extends React.Component {}
Correct way is the define your selector like this, so that it'll be only created once and the reference passes through your mapStateToProps argument.
const getSettings = () =>'sample output';
#connect(state => ({
getSettings,
}))
class Sample extends React.Component {}

Resources