DEV Community

Discussion on: How to Do a Device Based Code Split in React

Collapse
 
moubi profile image
Miroslav Nikolov

Andrew that looks ok and will also work in the last project I did.

I had to deal with different approaches for getting the touch/desktop detection right:

  • server side detection
  • using the browser string in the frontend
  • using media queries

Things may become very annoying, that's why I decided to back my self up.

The detection logic is central for the app so you can extract it to the store. I am personally using Redux.

To supplement what has already been said in the article here is an implementation for those using some kind of store (redux in here):

Reducer + selector

// ui.js reducer
import { qualifySelector } from "../utils";
import { mobileQuery } from "../../lib/mediaQueries";

const name = "ui";
const initialState = {
  isTouch: mobileQuery.matches
};

function reducer(state = initialState, action) {
  switch (action.type) {
    case "SET_TOUCH_SUCCESS":
      return {
        isTouch: action.payload
      };
    default:
      return state;
  }
}

export default { [name]: reducer };

export const isMobileView = qualifySelector(name, state => state.isTouch);
Enter fullscreen mode Exit fullscreen mode

And the<Import /> component.

// Import.js
import { useState, useEffect } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { isMobileView } from "../../../store/selectors";

export function Import({ touch, desktop, isMobile, children }) {
  const [Component, setComponent] = useState(null);

  useEffect(() => {
    const importCallback = isMobile ? touch : desktop;

    importCallback().then(componentDetails => {
      setComponent(componentDetails);
    });
  }, [desktop, touch, isMobile]);

  return children(Component ? Component.default : () => null);
}

Import.propTypes = {
  touch: PropTypes.func,
  desktop: PropTypes.func,
  children: PropTypes.func.isRequired,
  isMobile: PropTypes.bool.isRequired
};

export default connect(state => ({
  isMobile: isMobileView(state)
}))(Import);
Enter fullscreen mode Exit fullscreen mode

That way you will have detection logic agnostic approach and a central place to store the truth.

It may look like you are introducing a lot of unnecessary code, but it will pay off if your device detection changes dynamically during app lifecycle.


Fx. switching portrait to landscape mode may lead to serving desktop version instead of the touch one. Therefore you will need to update the store realtime with an action.