7

I get this error: Cannot read property 'getBoundingClientRect' of null. I use this function getBoundingClientRect, because in my project I want to have the following efect: at the moment one element is highlighted, the rest has different styles. The message shows the functions handleScroll. The component in which I use looks like this

class QuestionListItem extends Component {
  constructor() {
    super();
    this.state = {
      isActive: false,
    };

    this.handleScroll = this.handleScroll.bind(this);
  }

  componentDidMount = () => {
    window.addEventListener('scroll', this.handleScroll);
    this.handleScroll();
  };

  handleScroll = () => {
    const { isActive } = this.state;
    const { top } = this.wrapRef.getBoundingClientRect();
    if (top > 60 && top < 400 && !isActive) {
      this.setState({ isActive: true });
    }
    if ((top <= 60 || top >= 400) && isActive) {
      this.setState({ isActive: false });
    }
  }

  setWrapRef = (ref) => {
    this.wrapRef = ref;
  }

  render() {
    const { isActive } = this.state;
    const { question } = this.props;
    return (
      <div
        className={`Test__questions-item--noactive ${isActive && 'Test__questions-item--active'}`}
        ref={this.setWrapRef}
      >
        <li key={question.id}>
          <p>
            {question.question}
          </p>
          <QuestionAnswerForm name={question.question} />
        </li>
      </div>
    );
  }
}

Why is there such a mistake? Thanks for the help in advance :)

1

3 Answers 3

2

As I noticed your code, there you used arrow function with componentDidMount.

It should be:

componentDidMount() {}

also if you are using arrow function with handleScroll then there is no need to bind in the constructor, try to remove it and then modify the handleScroll as follows:

handleScroll = () => {
    const { isActive } = this.state;
    if (this.wrapRef) {
       const { top } = this.wrapRef.getBoundingClientRect();
       if (top > 60 && top < 400 && !isActive) {
          this.setState({ isActive: true });
       }
       if ((top <= 60 || top >= 400) && isActive) {
          this.setState({ isActive: false });
       }
    }
  }

Also remove function call this.handleScroll() after event listner in the componentDidMount as it is of no use.

Sign up to request clarification or add additional context in comments.

4 Comments

there is no error, however the state is not updated, styles do not change. As if the function handleScroll was not called
@Elder handleScroll only called if there is a scrollbar in your current component, I have no idea of style but there should be fixed height on the div with overflow property so that it has a scrollbar as it is assigned to scroll event listener
yes its works. I add componentWillUnmount() { window.removeEventListener('scroll', this.handleScroll); } and everything is ok :)
@Elder, please accept the answer if that helps you.
0

I think the problem is you have not created any ref for wrapRef. as the Error says cannot get the property of null; so the wrapRef itself is null

class QuestionListItem extends Component {
  constructor() {
    super();
    this.state = {
      isActive: false,
    };

    this.handleScroll = this.handleScroll.bind(this);
  }

  componentDidMount = () => {
    window.addEventListener('scroll', this.handleScroll);
    this.handleScroll();
  };

  wrapRef=React.createRef();

  handleScroll = () => {
    const { isActive } = this.state;
    const { top } = this.wrapRef.current.style;
    if (top > 60 && top < 400 && !isActive) {
      this.setState({ isActive: true });
    }
    if ((top <= 60 || top >= 400) && isActive) {
      this.setState({ isActive: false });
    }
  }

  render() {
    const { isActive } = this.state;
    const { question } = this.props;
    return (
      <div
        className={`Test__questions-item--noactive ${isActive && 'Test__questions-item--active'}`}
        ref={this.wrapRef}
      >
        <li key={question.id}>
          <p>
            {question.question}
          </p>
          <QuestionAnswerForm name={question.question} />
        </li>
      </div>
    );
  }
}

3 Comments

I do not understand what I should change
Edited the Answer
also pay attention to ref={this.wrapRef} in your div
0

Simply call the foo.getBoundingClientRect() inside a useEffect, which reads it when the component mounts. I was getting the same error.

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.