Search code examples
reduxmithril.js

Redux Selectors in Mithril


I've been tasked with implementing selectors in our redux application. Everything I'm reading online about redux selectors talks about React and how you can replace what is in mapStateToProps with a selector. What is the equivalent/where would i do this in a mithril app?


Solution

  • What is the equivalent/where would i do this in a mithril app?

    Firstly, you don't need an equivalent, you can just use the exact same selectors that you would in a React application.

    Where to call selectors?

    You can call the selectors wherever you want, but I recommend calling them as close to where the data is used as possible. Don't call selectors in a component high up in the component hierarchy only to pass the data down via several components before they end up in a component that actually uses the data – unless you have a good reason to do so.

    For most cases you can call the selectors inside a view-function, although you might come across cases where you need to call selectors in other lifecycle methods as well. In some applications you might also want to use selectors in m.render as well.

    A couple of examples off the top of my head:

    1. Inside the view function when creating DOM-elements

      var LoggedinUserDetails = {
          view: function () {
              return m('', [
                  m('', getLoggedinUserName(store.getState())), // getLoggedinUserName is a selector
                  m('img', { src: getLoggedinUserImageUrl(store.getState()) }) // getLoggedinUserImageUrl is a selector
              ])
          }
      }
      
    2. Inside the view function when creating Mithril components

      var UserDetails = {
          view: function (attrs) {
              return m('', [
                  m('', attrs.user.name),
                  m('img', { src: attrs.user.imageUrl })
              ])
          }
      }
      
          ...
          m(UserDetails, { user: getLoggedInUserDetails(store.getState()) }) // getLoggedInUserDetails is a selector
      
    3. Inside m.render

      In this example, we have a game that requires us to re-render the whole page after any change.

      function onStateChange() {
          var state = store.getState();
      
          m.render(document.body, m(Game, {
              map: getMap(state),
              players: getPlayers(state),
              visibleArea: getVisibleArea(state)
          }));
      }
      
      // Receiving partial state updates from server via websockets
      websocket.on('update-map', function (map) {
          store.dispatch({ type: 'update-map', payload: map });
      });
      
      websocket.on('update-players', function (players) {
          store.dispatch({ type: 'update-players', payload: players });
      });
      
      // Changing state based on user input
      window.addEventListener('keydown', function (event) {
          switch (event.key) {
              case 'Enter':
                  store.dispatch({ type: 'move-visible-area-to-next-player' });
                  break;
          }
      });