使用 styled-components 和 React setState 切换 body class

Toggle body class with styled-components and React setState

我正在尝试打开一个关闭的 canvas 菜单,然后在文档的其余部分应用 overflow-y: hidden; 以防止滚动。考虑到 React 和 styled-components 如何与 state.

一起工作,这非常困难

我将如何访问 body?我真的不想使用 document 到 get/set,因为这是 SSR Gatsby 站点,会引发错误。有没有一种本机方法可以用这个堆栈钻到那么高?

import React from 'react'
import styled from 'styled-components'

import NavMenu from '../NavMenu/navmenu.js'

// Styles, w/ styled-component syntax
const HeaderBG = styled.header`
  background-color: ${props => props.theme.purple};
  padding: 5px 25px;
`
const HeaderContainer = styled.section`
  align-items: center;
  display: flex;
  justify-content: space-between;
  margin: 0 auto;
  max-width: ${props => props.theme.xl};
`

const NavMenuButton = styled.div`
  cursor: pointer;
`

const NavMenuLine = styled.div`
  background: #fff;
  height: 2px;
  margin: 5px 0;
  transition-duration: .15s;
  transition-property: transform, opacity;
  transition-timing-function: ease-in-out;
  width: 25px;
`


// Header component
class Header extends React.Component {

  // Initial menu state is closed (false)
  constructor(props) {
    super(props)
    this.state = {
      menuStatus: false
    }
  }

  // Toggles menu open/close state
  menuToggle = () => {
    this.setState( prevState => ({
      menuStatus: !prevState.menuStatus
    }))
  }

  render() {
    return (  
      <div>
        <HeaderBG>
          <HeaderContainer>
            <NavMenuButton onClick={ this.menuToggle } menuState={ this.state.menuStatus }>
              <NavMenuLine></NavMenuLine>
              <NavMenuLine></NavMenuLine>
              <NavMenuLine></NavMenuLine>
            </NavMenuButton>
          </HeaderContainer>
        </HeaderBG>
      </div>
    )
  }
} 

如果您正在使用(或可以升级到)版本 4,则可以使用新的 createGlobalStyle helper。好处是您可以在代码中的任何地方实例化它。

事实上你可以使用新的'createGlobalStyle' 我很快为你整理了一个例子。

import React from 'react';
import PropTypes from 'prop-types';
import {createGlobalStyle} from 'styled-components';

const GlobalStyles = createGlobalStyle`
    overflow-y: ${({menuOpen}) =>
      menuOpen && hidden };
  }


export default class GlobalCss extends React.Component {
  state = {
    menuOpen: false
  };

  componentDidMount() {
    document.body.addEventListener('onToggleMenu', this.onMenuOpen, true);
  }

  componentWillUnmount() {
     document.body.removeEventListener('onToggleMenu', this.onMenuOpen, true);    
  }

  onMenuOpen = event => {
      this.setState({
        menuOpen: !this.state.menuOpen
      });
    }
  };

  render() {
    return <Styled.GlobalStyles menuOpen={this.state.menuOpen} />;
  }
}

您将组件添加到您的顶级组件中

  <GlobalStyles />