简体   繁体   中英

Uncaught Error: Too many re-renders in react

This is my code. Home.js I have used react-redux hooks useSelector and useDispatch to use state and dispatch requests.

import React from 'react'
import StyledBanner from '../../components/StyledBanner';
import FeaturedRoom from './FeaturedRoom';
import Hero from '../../components/Hero'
import {useDispatch, useSelector} from 'react-redux'
import {fetchRooms, fetchFeatured} from '../../redux'


function Home() {
    const dispatch = useDispatch()
    dispatch(fetchRooms())
    dispatch(fetchFeatured())
    const featuredRooms = useSelector(state=>state.roomReducer.featuredRooms)
    return (
        <div className="container-fluid p-0">
            <Hero>
                <StyledBanner title="best rooms" subtitle="subtitle">
                    <div className="subtitle">
                    </div>
                    <button className="btn btn-warning">Rooms</button>
                </StyledBanner>   
            </Hero>
            <FeaturedRoom featuredRooms={featuredRooms}/>
        </div>
    )
}

export default Home

This is FeaturedRoom.js

import React from 'react'
import StyledTitle from '../../components/StyledTitle';
import StyledButton from '../../components/StyledButton'
import {Link} from 'react-router-dom'

export function FeaturedRoom({featuredRooms}) {
    return (
        <div className="mt-3  mb-3 featured-container">
            <div className="featured-wrapper">
                <StyledTitle title="featured rooms"/>
                <div className="featured-rooms">

                    {
                        featuredRooms.map(room=>(
                            <div key={room.id} className="featured-item">
                                <div className="price-tag">
                                    <span>Rs {room.price}</span>
                                    <span>per night</span>
                                </div>
                                <img src={room.images[0]} className="img-fluid" alt="featured-img"/>
                                <Link to="/"><button>Room</button></Link>
                                <div className="room-name">
                                    {room.name}
                                </div>
                            </div>
                        ))
                    }


                </div>
            </div>
        </div>
    )

}

export default FeaturedRoom

In second part FeaturedRoom.js file, there is 'Link'. Until I click the button, everything works fine. Reducers are also working fine. All the reducers set state perfectly but, when I click on the button, it says

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
    at renderWithHooks (react-dom.development.js:14815)

Your issue lies in the Home component right after the dispatch assignment. You are calling dispatch with two actions in the Component definition. If you would like these actions to be fired upon mount, then put them in a useEffect hook.

import React, { useEffect } from 'react'
import StyledBanner from '../../components/StyledBanner';
import FeaturedRoom from './FeaturedRoom';
import Hero from '../../components/Hero'
import {useDispatch, useSelector} from 'react-redux'
import {fetchRooms, fetchFeatured} from '../../redux'


function Home() {
    const dispatch = useDispatch();
    const featuredRooms = useSelector(state=>state.roomReducer.featuredRooms)

    useEffect(() => {
        dispatch(fetchRooms())
        dispatch(fetchFeatured())
    }, [dispatch])

    return (
        <div className="container-fluid p-0">
            <Hero>
                <StyledBanner title="best rooms" subtitle="subtitle">
                    <div className="subtitle">
                    </div>
                    <button className="btn btn-warning">Rooms</button>
                </StyledBanner>   
            </Hero>
            <FeaturedRoom featuredRooms={featuredRooms}/>
        </div>
    )
}

export default Home

In this case, we are using the useEffect in a similar fashion to the old componentDidMount . The official docs for that hook are here .

It also occurs to me (given your function names) that you are trying to make a call to a repo to retrieve the featured rooms, load the result into the store, then select it from the store, then feed to FeaturedRoom component. If that's the case, I would recommend wrapping Home in a component that makes the call upon mount, and loads the redux store. A child component could then make use of the useSelctor hook, in conjunction with the useEffect hook (to watch for changes in the featuredRooms part of the store) to feed the results to FeaturedRoom . I hope that's somewhat clear.

Edit:

Ok, let's try this and see how it works for you. Move the selector inside the component that needs that data. Something like this:

import React, { useEffect } from 'react'
import StyledBanner from '../../components/StyledBanner';
import FeaturedRoom from './FeaturedRoom';
import Hero from '../../components/Hero'
import {useDispatch, useSelector} from 'react-redux'
import {fetchRooms, fetchFeatured} from '../../redux'


function Home() {
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchRooms())
        dispatch(fetchFeatured())
    }, [dispatch])


    return (
        <div className="container-fluid p-0">
            <Hero>
                <StyledBanner title="best rooms" subtitle="subtitle">
                    <div className="subtitle">
                    </div>
                    <button className="btn btn-warning">Rooms</button>
                </StyledBanner>   
            </Hero>
            <FeaturedRoom />
        </div>
    )
}

export default Home


function FeaturedRoom() {
    const featuredRooms = useSelector(state=>state.roomReducer.featuredRooms);

    /*  .... the rest of your component ... */
}

If you need to watch for changes on the featuredRooms property, you can place that logic in another useEffect within the FeaturedRoom component.

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