我正在使用react-responsive来获取媒体查询,并且我希望在屏幕尺寸之间共享一个组件状态,但是要使用不同的包装器。

例:

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>
    );
  }
}


在此示例中,我想使用另一个组件<ReactSwipe>封装<SignUpForm />。上面的方法有效,但是它正在创建3个SignUpForm实例...如果您调整浏览器的大小并碰到一个断点,则由于SignUpForm的新实例加载,您已经填写的任何表单数据都会丢失。如何将其更改为使用媒体查询,但只使用<SignUpForm />的一个实例。

最佳答案

嗯我对MediaQuery不熟悉,但是我会做不同的事情。我会编写/查找一个可以识别当前平台的函数,然后根据该函数进行切换:

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>
  );
}


另外,正如您在上面看到的那样,当函数可以使用时,我从不使用ES6类。我尝试尽可能少地使用类。这是个人喜好,但我确实发现它鼓励我编写更简单的代码。

如所要求的,这是findPlatform的一种可能的(未经测试的)实现。我将其放在自己的模块中,因此可以在测试过程中更轻松地对其进行模拟。

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';
}

09-25 16:43