Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
264 views
in Technique[技术] by (71.8m points)

javascript - After referring to document by querySelector I get an error in my React app - everything works fine until I scroll right to the bottom

I have a React app where I put a progress bar which changes its value once the user reaches some DOM elements. To build that feature I referred to window object with its 'scroll' properties:

// appointment.js
class Appointment extends React.Component {

    state = {
        progBarWidth: 33
    }

    checkCoordinates() {
        const stepTwoRect = document
            .querySelector('#stepTwo')
            .getBoundingClientRect().top

        const stepThreeRect = document
            .querySelector('#stepThree')
            .getBoundingClientRect().top

        if (window.scrollY >= stepTwoRect && window.scrollY < stepThreeRect) {
            this.setState({ progBarWidth: 66 })
        } 

        else if (window.scrollY < stepTwoRect) {
            this.setState({ progBarWidth: 33 })
        } 
        
        else if (window.scrollY >= stepThreeRect) {
            this.setState({ progBarWidth: 100 })
        }
    }

    componentDidMount() {
        window.addEventListener(
            'scroll',
            this.checkCoordinates.bind(this)
        )
    }

    componentWillUnmount() {
        window.removeEventListener(
            'scroll',
            this.checkCoordinates.bind(this)
        )
    }

    render() {
        return (
            <React.Fragment>  
                <div
                    className="progress position-fixed"
                >
                    <div
                        className="progress-bar"
                        style={{
                            width: `${this.state.progBarWidth}%`,
                        }}
                        aria-valuenow="33"
                        aria-valuemin="0"
                        aria-valuemax="100"
                    ></div>
                </div>

                <h1 id="greeting"> hello ! </h1>
    
                <h1>
                    Very long Lorem Ipsum to fill the page
                </h1>

                <h1 id="stepTwo"> Step 2 </h1>

                <h1>
                    Again very long Lorem Ipsum 
                </h1>

                <h1 id="stepThree"> Step 3 </h1>

                <h1>
                    Very long Lorem Ipsum
                </h1>
            </div>
        
            <div> 
        )
    }
}

The logic is that as I said once a user reaches #stepTwo, the progress bar should be filled by 66% in contrast to initial 33%, and once the user reaches #stepThree, it should be filled by 100%.

checkCoordinates does this function changing the state, and then that value is sent to width style property of progress bar.

I also made a bind for that function when adding event listener because it killed couple of my hours.

I think the problem is either in using document so when I go to other routes the app cannot reach #stepTwo and #stepThree (which are included only in appointment.js, however React puts everything in the root in index.html in the end). Or it is binding.

I tested in different browsers and tried to rerun the application however nothing helped me. I also get

TypeError: Cannot read property 'getBoundingClientRect' of null
Appointment.checkCoordinates
src/Appointment/Appointment.js:36
  33 | // }
  34 | 
  35 | checkCoordinates() {
> 36 |     const stepTwoRect = document
     | ^  37 |         .querySelector('#stepTwo')
  38 |         .getBoundingClientRect().top
  39 | 

together with 'can't find querySelector of null'.

Any thoughts?

P.S. when I just close the error by pushing X, everything works until I scroll until the very end of the page.

P.P.S. I noticed that when I use sass files for an individual component, styles apply to all the application components, not only the one for which it was created. I guess probably my app seeks for #stepOne on every page scroll, and when it cannot find, it throws an error..

P.P.P.S. I tried to bind the function once - just in the constructor. Now I have a problem with setState

question from:https://stackoverflow.com/questions/65829013/after-referring-to-document-by-queryselector-i-get-an-error-in-my-react-app-ev

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So the problem was with the bind. Bind creates new function every time even though I had removeEventListener element in componentWillUnmount.

Using Arrow function

    checkCoordinates = () => {...} 

helped both to bind and to use setState.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...