Categories
JavaScript Answers

How to Get the Height of the Entire Document with JavaScript?

Sometimes, we may want to get the height of the entire document with JavaScript.

In this article, we’ll look at how to get the height of the entire document with JavaScript.

Getting the Height of a Document

To get the height of a document, we can get the max of the scrollHeight, offsetHeight, or clientHeight properties.

For instance, we can write:

const body = document.body;
const html = document.documentElement;

const height = Math.max(body.scrollHeight, body.offsetHeight,
  html.clientHeight, html.scrollHeight, html.offsetHeight);
console.log(height)

The document can be stored in the document.body or document.documentElement properties depending on the browser used.

scrollHeight is a read-only property is a measurement of the height of an element’s content including the area that’s not visible on the page.

offsetHeight is a read-only property that returns the height of the element, including the vertical padding and borders as an integer.

clientHeight is a read-only property is the inner height of an element in pixels.

It includes the padding but excludes borders, margins, and horizontal scrollbars if they’re present.

Therefore, the max value between those would be the document’s height which includes everything.

The getBoundingClientRect Method

We can also use the getBoundClientRect method on the document element to get the height of it.

To use it, we write:

const body = document.body;
const html = document.documentElement;

const height = Math.max(body.getBoundingClientRect().height, html.getBoundingClientRect().height);
console.log(height)

We get the height of content of the document with the getBoundingClientRect method.

It returns an object with the height property to get the height of the content of the document.

The height is in pixels.

Conclusion

There’re various properties we can use to get the height of a document with JavaScript.

Categories
React

How to Add a Scroll Event Listener to a Scrollable Element in a React Component?

Sometimes, we may want to add a scroll event listener to a scrollable element in a React component.

In this article, we’ll look at how to add a scroll event listener to a scrollable element in a React component.

Add a Scroll Event Listener to a Scrollable Element in a React Component

We can pass in a callback function as the value of the onScroll prop of the scrollable element.

For instance, we can write:

import React, { useState, useRef } from "react";

export default function App() {
  const prevScrollY = useRef(0);
  const [goingUp, setGoingUp] = useState(false);

  const onScroll = (e) => {
    const currentScrollY = e.target.scrollTop;
    if (prevScrollY.current < currentScrollY && goingUp) {
      setGoingUp(false);
    }
    if (prevScrollY.current > currentScrollY && !goingUp) {
      setGoingUp(true);
    }
    prevScrollY.current = currentScrollY;
    console.log(goingUp, currentScrollY);
  };

  return (
    <div onScroll={onScroll} style={{ height: 300, overflowY: "scroll" }}>
      {Array(50)
        .fill("foo")
        .map((f, i) => {
          return <p key={i}>{f}</p>;
        })}
    </div>
  );
}

We have the prevScrollY ref to store the previous value of window.scrollY so we can compare with the current scrollY value to see if we’re scrolling up or down.

Then we define the goingUp state to let us track whether we’re scrolling up or down.

We get the e.target.scrollTop value to get the current vertical scroll position.

Then we compare the currentScrollY against the prevScrollY.current value.

If currentScrollY is bigger than the prevScrollY.current and goinUp is true , then we’re going down.

So we call setGoingUp with false to to indicate that we’re scrolling down.

On the other hand, if we have prevScrollY.current bigger than currentScrollY and goinUp is false , then we call setGoingUp to true to indicate that we’re scrolling up.

Then we set prevScrollY.current to currentScrollY to store the previous vertical scroll position

And then we login the value of goingUp and currentScrollY .

Below that, we add our scrollable div with the onScroll prop set to the onScroll function.

We set the height to a finite number so that we can make the div scrollable.

And we render the content of the div inside that.

Now when we scroll up and down, we see the goingUp and currentScrollY values logged.

Conclusion

We can watch the scroll position of a scrollable element by passing in a scroll event handler to the onScroll prop.

Categories
React

How to Update a State in a React Component in a Scroll Event Listener?

Sometimes, we may want to update a state in a React component in a scroll event listener.

In this article, we’ll look at how to update a state in a React component in a scroll event listener.

Adding a Scroll Event Listener into a React Component

We can add the code to add the scroll event listener into a React component’s useEffect hook.

The useEffect hook lets us commit side effects, so it’s appropriate for using it to watch scrolling location and update a state accordingly.

For instance, we can write:

import React, { useState, useEffect, useRef } from "react";

export default function App() {
  const prevScrollY = useRef(0);

  const [goingUp, setGoingUp] = useState(false);

  useEffect(() => {
    const handleScroll = () => {
      const currentScrollY = window.scrollY;
      if (prevScrollY.current < currentScrollY && goingUp) {
        setGoingUp(false);
      }
      if (prevScrollY.current > currentScrollY && !goingUp) {
        setGoingUp(true);
      }

      prevScrollY.current = currentScrollY;
      console.log(goingUp, currentScrollY);
    };

    window.addEventListener("scroll", handleScroll, { passive: true });

    return () => window.removeEventListener("scroll", handleScroll);
  }, [goingUp]);

  return (
    <div>
      {Array(50)
        .fill("foo")
        .map((f, i) => {
          return <p key={i}>{f}</p>;
        })}
    </div>
  );
}

We have the prevScrollY ref to store the previous value of window.scrollY so we can compare with the current scrollY value to see if we’re scrolling up or down.

Then we define the goingUp state to let us track whether we’re scrolling up or down.

Next, we add the useEffect hook with a callback that has the handleScroll function to let us compare the previous and current scrollY values.

If th prevScrollY.current value is less than the current one and goingUpis true, then we call setGoingUp to false to indicate that we’re scrolling down.

Otherwise, if we have prevScrollY.current value that is bigger than the current one and goingUp is false, then we call setGoingUp with true to indicate that we’re scrolling up.

We then set prevScrollY.current to the currentScrollY value since it’s going to become the previous value in the next render cycle.

Then we call window.addEventListener to add the scroll event listener.

window is the browser tab, so we watch the tab’s scrolling.

passive set to true means preventDefault will never be called in the event listener.

Then we return a function that calls removeEventListener to clear the scroll listener once we unmount the component.

Below that, we have an array of text we render into the page.

Now when we scroll up and down, we should see the console log log the goingUp value and the scroll Y position.

Conclusion

We can add a scroll event listener within the useEffect callback to listen to scrolling events.

Categories
React

How to Set State with a Deeply Nested Objects with React Hooks?

Sometimes, we may want to set the value of a state with a deeply nested object in our React components.

In this article, we’ll look at how to set a state with a deeply nested object with React hooks.

Setting a State Value to Deeply Nested Object

We can set a state value to a deeply nested object with the state setter function returned from the useState hook.

For instance, we can write:

import React from "react";

export default function App() {
  const [nestedState, setNestedState] = React.useState({
    propA: "apple",
    propB: "bar"
  });

  const changeSelect = (event) => {
    const newValue = event.target.value;
    setNestedState((prevState) => {
      return {
        ...prevState,
        propA: newValue
      };
    });
  };

  return (
    <React.Fragment>
      <div>{JSON.stringify(nestedState)}</div>
      <select value={nestedState.propA} onChange={changeSelect}>
        <option value="apple">apple</option>
        <option value="grape">grape</option>
        <option value="orange">orange</option>
      </select>
    </React.Fragment>
  );
}

We have the nestedState state defined with the useState hook.

Its initial value is set to an object with the propA and propB properties.

Next, we define the changeSelect function with the event parameter.

We get the drop down’s value with the event.target.value property.

Then we call setNestedState with a callback that has the prevState parameter.

prevState has the previous value of nestedState .

Then we return an object with the prevState spread into a new object.

And propA is set to newValue to set the new value of the propA property.

Below that, we have a stringified version of nestedState rendered.

And below that we have the select dropdown that has the value prop set to nestedState.propA .

And onChange is set to the changeSelect function to get the selected value and use the value to set nestedState with setNestedState .

Now when we select an option from the drop-down, then the latest value of the stringified nestedState object displayed.

Conclusion

We can set a state value to a deeply nested object by calling a state setter function with a callback that returns the latest value of a state.

Categories
React

How to Fix the React useState Hook Not Setting Initial Value Problem?

The useState hook lets us create state variables in our React components.

It takes an argument for the initial value of the state.

Sometimes, we may want to set the initial value of a state from props.

And we want to update the initial value when the prop value changes.

In this article, we’ll look at how to fix the React useState hook with the latest prop value.

Updating a State When a Prop Updates

To update a state when a prop updates, we’ve to watch the prop value with the useEffect hook.

Then in the useEffect callback, we can call the state setter function to update the state value with the prop’s value.

For instance, we can write:

import React, { useEffect, useState } from "react";

const Count = ({ count }) => {
  const [num, setNum] = useState(count);

  useEffect(() => {
    setNum(count);
  }, [count]);

  return <p>{num}</p>;
};

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <Count count={count} />
    </div>
  );
}

In the Count component, we have the useState hook with the count value as the argument.

This sets num to count initially.

Then we have the useEffect hook that watches the count value by passing it into the array in the 2nd argument.

Then in the callback, we call setNum to update the num value and render that in the return statement below that.

In App , we have the count state created with the useState hook.

Then we call setCount in the onClick handler of the button which updates the value of the count state.

And we pass the count value as the value of the count prop in the Count component.

Now when we click on the increment button, we see the num value update and the latest value of it displayed.

Conclusion

We can make sure that a React component state updates when the prop value changes by watching the prop’s value with the useEffect hook and then call the state setter function in the useEffect callback with the prop’s value as its argument.