【问题标题】:React conditionally render based on viewport sizeReact 根据视口大小有条件地渲染
【发布时间】:2018-03-17 02:30:49
【问题描述】:

这对你们 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 新手。

提前谢谢各位。

【问题讨论】:

  • 是否要在页面调整大小时更新isDesktop
  • 嗯,好问题。我会说是的。当用户调整大小时,当宽度低于 1450 像素时,它应该呈现正确的组件。我正在尝试在没有 CSS 的情况下锻炼响应能力

标签: reactjs


【解决方案1】:

也许我应该使用 ComponentWillMount 或 ComponentDidMount 来处理它

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

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

【讨论】:

  • 那是黄金!我现在明白了这个概念。我应该能够在我必须解决的其他条件下使用这个概念。谢谢!
  • 好答案,彻底展示了​​条件状态变化的架构。
【解决方案2】:

在我遇到同样的问题后在这里发布最近的更新,但使用功能组件和 useEffect / useState React 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>
  );
}

【讨论】:

  • 就像字面上的复制粘贴和编辑一样,这行得通,yassssssss!谢谢! @foakesm
【解决方案3】:

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

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

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

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

【讨论】:

    【解决方案4】:

    您的代码的问题是它仅在调整大小发生时才有效,这里我有 handleWindowResiz 函数将宽度设置为 window.innerWidth 并将其与 breakPoint 进行比较以有条件地呈现您的 UI,如果用户调整屏幕大小,事件侦听器将被触发,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>

    【讨论】:

    • 如果你能解释一下你用你的代码做什么就好了。
    • 第一次渲染组件时,handleWindowResize函数会设置初始宽度,然后我们将宽度与断点进行比较来选择应该渲染的内容
      我显示在1451px或更高 或
      I show on 1450px 或更低
      ,当窗口调整大小时,将触发事件侦听器并将宽度重置为新的窗口宽度。所以这里的不同之处在于,即使在第一次渲染组件时,我们也可以获得窗口宽度并进行条件渲染。我希望我能够很好地解释自己:)
    • 请将解释放在答案中,不要放在评论中。
    【解决方案5】:
    class My Class extends React.Component {
      constructor(props) {
          super(props);
          this.state = {
              isDesktop: window.innerHeight > 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>
          );
      }}
    

    这里有更多信息Get viewport/window height in ReactJS

    【讨论】:

    • 不幸的是,它没有工作,innerHeight 也引起了我的注意。你不是在处理高度而不是宽度吗?我的意思是处理视口的宽度。我尝试了innerWidth,它也没有工作。不过,我还没有检查您提供的链接
    • 你可以创建resize listener,带有回调函数,可以改变isDesktop的状态,目前这个实现只在刷新页面时起作用
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签