Skip to content

Instantly share code, notes, and snippets.

@json2d
Last active February 9, 2020 03:56
Show Gist options
  • Save json2d/e7f65204cf271063cc7e29dd5f14a0b7 to your computer and use it in GitHub Desktop.
Save json2d/e7f65204cf271063cc7e29dd5f14a0b7 to your computer and use it in GitHub Desktop.
proposal to put state into callback scope through 'this'
const entryByIdSelector = (state) => state.todos.entrybyId
const recentIdsSelector = (state) => state.todos.recentIds
const entrySelector = _.memoize(
(id) => createSelector(
entryByIdSelector,
(entryById) => entryById[id]
)
)
const recentSelector = createSelector(
recentIdsSelector,
function (ids) {
return ids.map( id => entrySelector(id)(this.state /* magic */ ) )
}
)
@json2d
Copy link
Author

json2d commented Jun 29, 2019

heres a way (with its own tradeoffs) achieving the same result w/o having a state arg

it parametizes ids (previously recentIds) outside of createSelector, and with a little bit more finesse its able to use createSelector as intended to memoize

const entriesSelector = _.memoize( 
  (ids) => createSelector(
    ...ids.map(id => entrySelector(id)),
    (...entries) => entries
  )
)

now the kinda ugly part

what we need to do is take the result of recentIdsSelector and use it as the ids arg in entriesSelector.

to do this we'll jump into react-redux land (where we actually use our reselectors) and use 2 levels of connect, one around the other.

const mstp = (state) => ( { recentIds: recentIdsSelector(state) } ) 
const mstp2 = (state, props) => ( { recentEntries: entriesSelector(props.recentIds)(state) } )

let RecentContainer = compose(
  connect(mstp), 
  connect(mstp2)
)(Recent)

this might just be the best way, as there seems to be no way to write the recentSelector (see prev comments) as a single reselector

connect acts like the glue for our new selector code, giving us the desired high-level behavior:

  • recentEntries will only be recomputed if:
    • state.recentIds changes
    • an entry in state.entryById with one of those ids changes

in general this is how you could use result of one reselector as the arg of another reselector without breaking memoization that reselect provides

@json2d
Copy link
Author

json2d commented Jun 29, 2019

...or just deal with a potential performance hit when doing it all in one connect 🥇

const mstp = (state, props) => { 
  const recentIds = recentIdsSelector(state)
  const recentEntries = entriesSelector(recentIds)(state)
  
  return { recentEntries }
}

let RecentContainer = connect(mstp)(Recent)

same high-level behavior

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment