根据视口大小进行有条件的渲染

IT技术 reactjs
2021-05-11 07:28:35

这对你的 React 怪物来说应该是一件容易的事。:) 我写了条件,但我不知道如何在我的构造函数中处理视口大小以使条件起作用。简单明了,我想在视口大小为 1451 像素或更宽时显示一个元素,而在 1450 像素或更小时显示另一个元素。

这是我的代码(简化)

class My Class extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isDesktop: "1450px" //This is where I am having problems
        };
    }

    render() {
        const isDesktop = this.state.isDesktop;

        return (
            <div>
                {isDesktop ? (
                    <div>I show on 1451px or higher</div>
                ) : (
                    <div>I show on 1450px or lower</div>
                )}
            </div>
        );
    }
}

也许我应该将它与 ComponentWillMount 或 ComponentDidMount 一起使用。老实说,不确定。我是 React 的新手。

在此先感谢各位。

4个回答

也许我应该与 ComponentWillMount 或 ComponentDidMount 一起工作

是的,您需要监听resize事件并在更改时更新内部状态。您可以通过在组件安装时添加事件处理程序来实现。在此处尝试完整示例

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isDesktop: false //This is where I am having problems
    };

    this.updatePredicate = this.updatePredicate.bind(this);
  }
  componentDidMount() {
    this.updatePredicate();
    window.addEventListener("resize", this.updatePredicate);
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.updatePredicate);
  }

  updatePredicate() {
    this.setState({ isDesktop: window.innerWidth > 1450 });
  }

  render() {
    const isDesktop = this.state.isDesktop;

    return (
      <div>
        {isDesktop ? (
          <div>I show on 1451px or higher</div>
        ) : (
          <div>I show on 1450px or lower</div>
        )}
      </div>
    );
  }
}

只是在我遇到同样的问题后在这里发布最近的更新,但使用功能组件和useEffect/ useStateReact Hooks 进行设置:

const MyFunction = () => {
  const [isDesktop, setDesktop] = useState(window.innerWidth > 1450);

  const updateMedia = () => {
    setDesktop(window.innerWidth > 1450);
  };

  useEffect(() => {
    window.addEventListener("resize", updateMedia);
    return () => window.removeEventListener("resize", updateMedia);
  });

  return (
    <div>
      {isDesktop ? (
        <div>I show on 1451px or higher</div>
      ) : (
        <div>I show on 1450px or lower</div>
      )}
    </div>
  );
}

如果你使用NextJS ... 你会得到一个类似的错误:window is not defined这是没有错误的代码,享受。

首先我检查窗口的大小是否大于或小于 1450px(因为如果用户从不调整窗口大小,所有代码都将无用)

但我还需要检查用户是否调整了窗口大小......自己看

    export default function MyFunction() {
        const [isDesktop, setDesktop] = useState(false);

  useEffect(() => {
    if (window.innerWidth > 1450) {
      setDesktop(true);
    } else {
      setDesktop(false);
    }

    const updateMedia = () => {
      if (window.innerWidth > 1450) {
        setDesktop(true);
      } else {
        setDesktop(false);
      }
    };
    window.addEventListener('resize', updateMedia);
    return () => window.removeEventListener('resize', updateMedia);
  }, []);
    
      return (
          <div>
              {isDesktop ? (
                  <div>I show on 1451px or higher</div>
              ) : (
                  <div>I show on 1450px or lower</div>
              )}
          </div>
      );
    }

与您的代码的问题是,如果调整大小发生了,它才能正常运行,在这里我有handleWindowResiz功能将宽度设置为window.innerWidth,并将其与该breakPoint有条件地呈现你的用户界面,如果用户调整画面的事件监听器将被触发,在handleWindowResiz将被调用,它会重置width到新的window.innerWidth,你会得到你想要的UI。因此,当组件第一次呈现和用户调整屏幕宽度时,UI 总是正确呈现。

const MyFunction = () => {

  const [width, setWidth] = React.useState(window.innerWidth);
  const breakPoint = 1450;

 

  useEffect(() => {
   const handleWindowResize = () => setWidth(window.innerWidth);
   window.addEventListener("resize", handleWindowResize);

    
   return () => window.removeEventListener("resize", handleWindowResize);
  },[]);

  return (
    <div>
      {width > breakPoint? (
        <div>I show on 1451px or higher</div>
      ) : (
        <div>I show on 1450px or lower</div>
      )}
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>