Code Monkey home page Code Monkey logo

redux-mediaquery's Introduction

redux-mediaquery

👉 Watch me present this at React Europe 2016 👈

Intro

This is an ActionCreator for Redux that makes CSS mediaqueries (and more) available in the store. This allows you to declaratively make responsive layouts.

It is very small, without any dependencies, except that the reducer requires Object.assign().

Use Cases

  • Complement CSS, rendering fully different components depending on screen size instead of just showing/hiding parts of the application
  • Update measuring components when screen size changes
  • responsive images
  • flag server-side rendering

How to use

  1. npm install --save redux-mediaquery
  2. In your store creator, import the reducer and action:
import {reducer as responsive, mediaQueryTracker} from 'redux-mediaquery'
  1. Add it to the reducers:
const reducer = combineReducers({
  responsive,
  ...reducers,
})
  1. After the store is created, indicate the properties that you are interested in:
const unlisten = mediaQueryTracker({
  isPhone: "screen and (max-width: 767px)",
  isTablet: "screen and (max-width: 1024px)",
  innerWidth: true,
  innerHeight: true,
}, store.dispatch)

You can call unlisten() when you need to remove the listener it puts on window, for example when you are hot reloading.

Note: If you want, you can dispatch mediaQueryTracker(...) as an action. In that case, do not provide the dispatch argument. This requires you to use the redux-thunk middleware.

  1. Connect components to the store and conditionally render things:
@connect(({responsive}) => ({
  isPhone: responsive.isPhone,
  innerHeight: responsive.innerHeight,
}))
class SomeComponent extends React.Component {
  render() {
    const {isPhone, innerHeight} = this.props
    return (
      <div>
        {isPhone ? (
          <h1>I'm on a phone!</h1>
        ) : (
          <p>Desktop here. My height is {innerHeight}</p>
        )}
      </div>
    )
  }
  1. sit back and relax 🏝

Pro Tip: write your media queries so false is the default, for server side rendering or in case matchMedia doesn't exist

Browser Support

For innerWidth/innerHeight, IE9 is sufficient. For the mediaqueries, this relies on matchMedia() support in the browser, and thus requires Internet Explorer 10+.

ChromeFirefox (Gecko)Internet ExplorerOperaSafari
96.0 (6.0)1012.15.1
Android Firefox Mobile (Gecko) IE Mobile Opera MobileSafari Mobile
3.06.0 (6.0)No support12.15

Object.assign() needs to be polyfilled if missing. (It is probably already available, through your JSX build)

Server-side rendering

If you combine this with a library like https://github.com/hgoebl/mobile-detect.js, you can decide on the server whether to render for a phone or for desktop, or even for search bots.

To do this, derive e.g. isPhone and isBot from the user-agent header. Then initialize the Redux store, and dispatch the mediaChanged action:

import {mediaChanged} from 'redux-mediaquery'

// ... create store

store.dispatch(mediaChanged({isServer: true, isPhone, isBot}))

Then, in your app, decide what to do with isServer and isBot. Finally, in the browser build, dispatch isServer: false after the first render (use the callback in React.render(app, element, callback) for that).

By updating isServer only after the first render, you make sure that React can re-use the pre-rendered content.

Changelog

  • v0.11:
    • remove reliance on redux-thunk (backwards-compatible)
    • unlisten for hot reload etc
    • some tests
  • v0.10:
    • change the action type string to have '@@' as a prefix (@moimikey)

Ideas for future development

  • uglify build
  • stable API once more feedback from community
  • other special measurements? e.g. "is actual phone", "has touch", …
  • a collection of breakpoints/queries?
  • server side helpers for converting from user agent string to redux actions
  • demo page

redux-mediaquery's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

redux-mediaquery's Issues

doesn't fire action...?

I have installed your redux-mediaquery, and followed the instructions 1-4, but it didn't fire any media change actions when I changed window size.

Are there any reasons that you can imagine?

Here is my package.json:

{
  "name": "name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start-native": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest src",
    "test-native": "jest --config=jest.config.json __tests__/*",
    "build-web": "webpack --config webpack.production.config.js --progress --profile --colors",
    "start-web": "webpack-dev-server --progress --profile --colors",
    "lint": "eslint --ext js --ext jsx src || exit 0",
    "dev-web": " webpack-dashboard -- webpack-dev-server --progress --profile --colors",
    "storybook-web": "start-storybook -p 9000",
    "build-storybook": "build-storybook"
  },
  "dependencies": {
    "history": "^4.6.1",
    "i18next": "^8.3.0",
    "material-ui": "^0.18.1",
    "node-sass": "^4.3.0",
    "raw-loader": "^0.5.1",
    "react": "16.0.0-alpha.6",
    "react-dom": "16.0.0-alpha.6",
    "react-i18next": "^4.1.0",
    "react-redux": "^5.0.5",
    "react-router": "^3.0.5",
    "react-router-redux": "^4.0.8",
    "react-tap-event-plugin": "^2.0.1",
    "redux": "^3.6.0",
    "redux-logger": "^3.0.6",
    "redux-mediaquery": "^0.10.0",
    "redux-thunk": "^2.2.0",
    "redux-ui": "^0.1.1",
    "sass-loader": "^6.0.2"
  },
  "devDependencies": {
    "babel-cli": "6.24.1",
    "babel-core": "^6.23.1",
    "babel-jest": "20.0.3",
    "babel-loader": "^6.3.2",
    "babel-plugin-transform-class-properties": "^6.22.0",
    "babel-plugin-transform-decorators": "^6.24.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-preset-env": "^1.5.1",
    "babel-preset-es2015": "6.22.0",
    "babel-preset-react": "^6.23.0",
    "babel-preset-react-native": "1.9.2",
    "babel-preset-stage-0": "^6.24.1",
    "babel-runtime": "^6.22.0",
    "css-loader": "0.26.1",
    "extract-text-webpack-plugin": "^v2.0.0-rc.1",
    "file-loader": "^0.10.0",
    "form-data": "^2.1.4",
    "html-webpack-plugin": "^2.26.0",
    "http-shutdown": "^1.2.0",
    "jest": "20.0.3",
    "jest-react-native": "^18.0.0",
    "postcss-loader": "^1.2.2",
    "react-hot-loader": "^3.0.0-beta.6",
    "react-test-renderer": "16.0.0-alpha.6",
    "redux-mock-store": "^1.2.3",
    "style-loader": "0.13.1",
    "url-loader": "0.5.7",
    "w3c-xmlhttprequest": "^2.1.2",
    "webpack": "^2.2.1",
    "webpack-cleanup-plugin": "^0.4.2",
    "webpack-dashboard": "^0.3.0",
    "webpack-dev-server": "^2.4.1",
    "@storybook/react": "^3.0.1"
  },
  "jest": {
    "globals": {
      "__DEV__": true
    }
  },
  "rnpm": {
    "assets": [
      "./roboto-fonts"
    ]
  }
}

Getting error from redux - on dispatch:

I'm using create-react-app and was sort of following along with another tutorial and wanted to try out this library - I was wondering if anything has changed in redux that doesn't allow functions like this anymore?

I'm using [email protected] if it makes any difference

Thanks in advance, looks like a great library!

I'm a bit of a novice, but if you give me some direction I could try a PR for fixing the trackMediaQueries method that is the default export

Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
at dispatch (createStore.js:166)
at Object.dispatch (middleware.js:80)
at configureStore (configureStore.js:18)
at Object. (index.js:9)
at webpack_require (bootstrap 7138f6b…:555)
at fn (bootstrap 7138f6b…:86)
at Object. (bootstrap 7138f6b…:578)
at webpack_require (bootstrap 7138f6b…:555)
at bootstrap 7138f6b…:578
at bootstrap 7138f6b…:578

LMIT-PAUL:cb-ui paul$ yarn list redux
yarn list v0.19.1
└─ [email protected]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.