简体   繁体   中英

React infinite render loop

I have created a component which needs to be individually displayed in multiple parts of the application - (inside of my navigation, on the home page and on a separate route). Therefore, I made all my action dispatches (api calls for reading data) inside a useEffect in this component:

useEffect(() => {
    dispatch(time.read())
    dispatch(pause.read())
    dispatch(travel.read())
    dispatch(distances.read())
}, [])

As you can see, this effect should only run once (when the component mounts).

Nowhere else do I dispatch these specific actions inside or outside of this component.

This component is rendered in 3 places (inside of the nav, in its own /time route and inside of the home component). I can render it inside of the navigation and on /time at the same time without a problem. It acts as it should (when I make changes from the navigation, they are mirrored on /time since it is all tied together with redux). Finally there is the Home component.

When I first tried to render on the Home component, it took a while to load, then I tried opening it up from my mobile device through my v4 address (same network), it took too long to load. At this point my laptop started sounding like a helicopter, so I opened htop, memory usage and CPU usage was pretty much maxed out, I opened up my server logs and saw hundreds of requests per second. Here is how I render this component inside my Home component:

import React from "react"
import { useSelector } from "react-redux"
import { NavLink } from "react-router-dom"
import "./Home.css"

import {
    FaCarCrash,
    CgProfile,
    AiOutlineShop,
    TiVideo,
} from 'react-icons/all'
import Tracking from "../TimeTracking/Tracking" /*This is the component which causes all the toruble*/

export default function Home(props) {

    const current = useSelector(state => state.user.currentUser)

    return (
        <div className="Home container">
            <div id="links">
                <NavLink to="/create_job/">
                    <FaCarCrash />
                    <p> CREATE JOB </p>
                </NavLink>
                <NavLink to={"/profile/" + current._id}>
                    <CgProfile />
                    <p> PROFILE </p>
                </NavLink>
                <NavLink to="/shop/view/">
                    <AiOutlineShop />
                    <p> SHOP </p>
                </NavLink>
                <NavLink to="/tutorials/">
                    <TiVideo />
                    <p> TRAINING </p>
                </NavLink>
            </div>
            <Tracking /> /*This is the component which causes all the toruble*/
        </div>
    )
}

As you can see, nothing out of the ordinary - a simple functional component which doesn't even dispatch any actions. Only communication with redux here is the useSelector.

Here is where I render the Home component:

import React, { Fragment } from 'react'
import { Route } from 'react-router-dom'

/*...other imports...*/
import Home from "../components/Mobile/Home"
/*...other imports...*/

export default props => (
    <Fragment>
        /*...other routes...*/
        <Route path="/home" component={Home} />
        /*...other routes...*/
    </Fragment> /* just a fragment wrapper around the routes for the user. This component is later rendered inside of my <Router> </Router>. This is done because the app has a lot of different routes. */
)

For some reason, this component keeps re-rendering over and over again, even if I do not interact with the application. I've checked to see if I am ever dispatching the same action from 2 places which could cause this issue, but I am not. I know I haven't given a lot to go on, but there is really not that much to show in this issue, I'm just hoping someone has encountered it before. I've dealt with infinite render loops before, they are usually obvious and easy to solve but this one is a bit odd.

I have solved my problem. I was actually using the old version of my RootRouter.js which had the Home component declared like so:

<Route path="/home" component={<Home user={this.props.user} />} />

And the Home component I was rendering was also an older version (it was a class component, not the function component I wrote in the question).

So here is what caused the issue:

the user prop is passed down when declaring the Home route, and it holds the value of state.user

Then in the Home component, I am using mapStateToProps and mapping the user to the props , and setting it to state.user.currentUser .

This causes the user prop to be declared once when rendering the component, then changing once the component is rendered, and then it will change again on the next render and so on. The reason why react did not respond to the render loop is because the user prop holds a different value for each render.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM