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.
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.