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

时间:2018-01-10 15:38:50

标签: javascript reactjs

我正在使用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 />。上面的工作,但它创建了SignUpForm的3个实例...如果您调整浏览器的大小并点击断点,您填写的任何表单数据都将在SignUpForm的新实例加载时丢失。如何更改此选项以使用媒体查询,但只有<SignUpForm />的一个实例。

1 个答案:

答案 0 :(得分:2)

嗯。我不熟悉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';
}