简体   繁体   English

React.js-根据媒体查询将共享组件包装在不同的组件中

[英]React.js - Wrap a shared component in different components based on media queries

I'm using react-responsive to get media queries and I want to have one component state being shared across screen sizes, but using different wrappers. 我正在使用react-responsive来获取媒体查询,并且我希望一种组件状态在屏幕尺寸之间共享,但是使用不同的包装器。

Example: 例:

import MediaQuery from 'react-responsive';
import ReactSwipe from 'react-swipe';

const Desktop   = props => <MediaQuery {...props} minWidth={992} />;
const Tablet    = props => <MediaQuery {...props} minWidth={768} maxWidth={991} />;
const Mobile    = props => <MediaQuery {...props} maxWidth={767} />;

export class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <Desktop>
          <SignUpForm />
        </Desktop>
        <Tablet>
          <SignUpForm />
        </Tablet>
        <Mobile>
          <ReactSwipe>
            <SignUpForm />
          </ReactSwipe>
        </Mobile>
      </div>
    );
  }
}

In this example, I want to use another component <ReactSwipe> to encapsulate <SignUpForm /> . 在此示例中,我想使用另一个组件<ReactSwipe>封装<SignUpForm /> The above works, but it's creating 3 instances of SignUpForm ... if you resize the browser and hit a breakpoint any form data you have filled out already will be lost as the new instance of SignUpForm loads. 上面的方法有效,但是它正在创建3个SignUpForm实例...如果您调整浏览器的大小并碰到断点,则由于SignUpForm的新实例加载,您已经填写的任何表单数据都会丢失。 How do I change this to use media queries but one instance of <SignUpForm /> . 如何更改为使用媒体查询,但只使用<SignUpForm />一个实例。

Hm. I'm not familiar with MediaQuery, but I'd do this differently. 我对MediaQuery不熟悉,但是我会做不同的事情。 I'd write / find a function that identifies the current platform and then switch based on that: 我会编写/查找一个可以识别当前平台的函数,然后根据该函数进行切换:

const wrappers = {
  desktop: Desktop,
  tablet: Tablet,
  mobile: Mobile, // I'd have this wrapper do the ReactSwipe thing
};

export function App() {
  // returns a string that is one of: 'desktop', 'tablet', 'mobile'
  const platform = findPlatform();
  const Wrapper = wrappers[platform];

  return (
    <Wrapper>
      <SignUpForm />
    </Wrapper>
  );
}

Also, as you'll see above, I never use ES6 classes when a function will do. 另外,如您在上面看到的那样,当函数可以使用时,我从不使用ES6类。 I try to use classes as infrequently as possible. 我尝试尽可能少地使用类。 This is personal preference, but I do find that it encourages me to write simpler code. 这是个人喜好,但我确实发现它鼓励我编写更简单的代码。

As asked, here's a possible (untested) implementation of findPlatform . 如所要求的,这是findPlatform的一种可能的(未经测试的)实现。 I'd put this in its own module, so it can be mocked more easily during testing. 我将其放在自己的模块中,因此可以在测试过程中更轻松地对其进行模拟。

function findPlatform() {
  const minTabletSize = 768; // Make this whatever you think is best

  if (!(/Mobi/.test(navigator.userAgent))) {
    return 'desktop';
  }

  if (window.outerHeight > minTabletSize || window.outerWidth > minTabletSize) {
    return 'tablet';
  }

  return 'mobile';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM