Result functions of type x => x are unnecessary? - redux

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

Related

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.

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 {}

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

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
);

Compare & contrast redux reselect vs lodash / underscore memoize...?

I was wondering if someone can compare & contrast the differences between redux reselect lib vs lodash memoize...?
Lodash's memoize is a classic memoizing utility: It memoizes a function using (by default) its first argument as cache key. Lodash's memoize keeps track/caches all the results obtained with different cache keys.
Reselect instead, checks each provided argument, and (by default) recomputes the result ONLY IF one of the arguments changes. Reselect's selectors have by default a cache size of 1, and are mainly designed to stabilize state-derived data avoiding undesired recomputations.
There are 2 major differences:
are all parameters checked for changes before recomputing, or just the first one?
are all results cached, or only the most recent result?
lodash _.memoize:
only checks the first parameter for changes and returns the most recent result for that first parameter, regardless of whether other parameters have changed (by default).
keeps an infinitely large record of all result values keyed by that first parameter.
Example of a problematic case with lodash _.memoize:
const memoizedFunc = _.memoize(
(param1, param2) => param1 + param2
);
console.log(memoizedFunc(1, 2)); // 3
console.log(memoizedFunc(1, 3)); // 3 (but it should be 4!)
Note that you can write a custom resolver function and pass it in as the second argument to _.memoize to change this behavior and thus take all or some parameters into account. This is extra logic to test and maintain and may or may not be worth it to you. (The resolver function determines the key to be used in the Map of cached results that the memoized function maintains. By default the key is just set to equal the first parameter.)
reselect:
checks all parameters for equality against the most recent execution only.
only caches a single result (the most recent).
Note that reselect is primarily used for redux applications, creating memoized selectors with createSelector. In createSelector, each parameter is expected to have a getter (selector) function, because of the expectation of usage with a redux store. If you are not trying to memoize data from a redux store, you still could use this and send in an identity function like _.identity for each parameter, but that would be silly.
Fortunately, if you only want to memoize functions, and you want all parameters checked for changes, you can use reselect's defaultMemoize and get the desired behavior.
Summary / other libraries (memoize-one)
If you want all parameters checked for changes, and are not using redux or otherwise need to use createSelector, you may want to just use a very lightweight and fast library intended for specifically for this like memoize-one.
If you do want createSelector, you can just use reselect for all your needs most likely.
If you want all results to be cached, not just the most recent ones, you can use lodash _.memoize alone, and you can also customize reselect to use that feature of lodash _.memoize.

Resources