Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access <body> from React

I'm new to React and I am trying to build a standalone Header component containing a 'slide in sidebar'. I used state to apply CSS to slide the sidebar in/out:

constructor() {
super();
  this.state = {
    sideBar: false
  }
}
handleSidebar() {
  this.setState({
    sideBar: !this.state.sideBar
  });
}
render() {
return(
  <header>
   <ul style={this.state.sideBar ? {'transform': 'translateX(0%)'} : null}></ul>
   <button onClick={this.handleSidebar.bind(this)}></button>
  </header>
)

This does the job in terms of sliding the sidebar, but once the sidebar is open, I would like to lock scroll on body by applying overflow:hidden to the <body>. However since <body> is outside of React, I was wondering how it's possible to access the tag?

Link to Codepen

like image 672
Jan Cziżikow Avatar asked Sep 10 '17 16:09

Jan Cziżikow


People also ask

How do you access the body element in React?

We can access the body element on the document object. You can use the style object to read an element's styles or set new styles on the element. If you need to add a class to the body element, use the classList. add method.

Can we use body tag in React?

To add a class to the body element in React: Access the body element as document. body in useEffect or an event handler.

Can you access DOM in React?

In React we can access the DOM element using Refs. Refs provide a way to access DOM nodes or React elements created in the render method. Creating Refs: Refs are created using React. createRef() and attached to React elements via the ref attribute.

Can you React to access window object?

Any property attached to the window object can be accessed from any script on the web page, including the script for the React app. Since window is a global object, the React code can also access its properties, as shown below.


1 Answers

Use document.body to set the styles you need. Make sure you access document after it's ready, so put the code in componentWillMount. You should reset the styles after unmounting the component in componentWillUnmount.

componentWillMount() {
    document.body.style.overflow = "hidden";
}

componentWillUnmount() {
    document.body.style.overflow = "visible"; // or restore the original value
}

After your comment I realized that you need to set the styles after opening the sidebar. Here some notes:

  1. Don't use this.state in setState. setState is asynchronous, therefore you should use the optional prevState parameter to access the previous state object.
  2. You could use the optional second parameter of setState which is a function and is called after the state is updated. In this function you could set the styles of the body.
  3. You can bind the function in the constructor.
  4. In the constructor pass the props to the base constructor (super(props)).
  5. Rename sideBar to isSideBarOpen. It is a more descriptive name.

Here is the final code:

constructor(props) {
    super(props);
    this.state = {
        isSideBarOpen: false
    };
    this.toggleSideBar.bind(this);
}

updateBodyStyles() {
    if (this.state.isSideBarOpen) {
        document.body.style.overflow = "hidden";
    } else {
        document.body.style.overflow = "visible";
    }
}

toggleSideBar() {
    this.setState((prevState) => {
        return { isSideBarOpen: !prevState.isSideBarOpen }
    }, this.updateBodyStyles);
}

render() {
    return (
       <header>
            <ul style={this.state.isSideBarOpen? {'transform': 'translateX(0%)'} : null}></ul>
            <button onClick={this.toggleSideBar}></button>
       </header>
    )
like image 149
Dávid Molnár Avatar answered Sep 21 '22 12:09

Dávid Molnár