Reputation: 13
function QuestionAns(){
const url = 'http://127.0.0.1:8000/'
const [data, setData] = useState([]);
const [currData, setCurrData] = useState([])
let i = 1
useEffect(() => {
let result = []
const fetchFromUrl = async() => {
const response = await axios.get(url)
const response_data = await response.data.data
await setData(response_data)
}
fetchFromUrl()
}, [])
const run_loop = async ()=>{
let arr = []
for(let counter = 0; counter < 12; counter++){
arr.push(<Pretty count={i} question={data[i].question} answer_option={data[i].option_arr} answer={data[i].answer} key={data[i]._id} corr_ans={data[i]._id}/>)
i+=1
}
let dat = await arr.concat(currData)
await setCurrData(dat)
}
if(data.length){
run_loop()
}
return (
<div className="container my-3">
<div className="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-5">
{data.length ? currData : `loading`}
</div>
</div>
)
}
export default QuestionAns;
In this function fetchFromUrl we are getting the data from the server which is stored in the data state again I am taking 12 data from the fetched content and storing it to currData. Purpose is to make a infinite scroll. but if I keep the code like that I am getting a infinite entries of 12 data means 1 to 12 -> 1 to 12 -> 1 to 12 ..... . Problem lies with currData.
Any idea why I am getting in this infinite loop. I am good with raw js and can do this this easily but I am learning react now so any help will be appriciated.
I was expecting the data from 1-12 will load single time.
Upvotes: 0
Views: 162
Reputation: 16169
if(data.length){
run_loop()
}
this condition
is always true
expect for the first render before running useEffect
but once fetchFromUrl()
is executed data.length
become true
forever since inside this function
you are updating the useState hook
setData(response_data)
if(data.length)
returns true
if data.length > 0
which is always the case unless response.data.data
is an empty array
after what happens ? run_loop()
executes and updates currData
setCurrData(dat)
and this will re-render the component and since if(data.length)
is always true
this will happen infinitely.
so I guess you are getting an infinite render not an infinite loop. try to console.log
from inside your jsx
to be sure
return (
<div className="container my-3">
{console.log('this is a new render')}
<div className="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-5">
{data.length ? currData : `loading`}
</div>
</div>
)
what you should do is to make run_loop()
part of fetchFromUrl
so it runs inside useEffect
I don't understand but this is what your code is doing if(data.legth){run_loop()}
useEffect(() => {
let result = [];
let arr = []
const fetchFromUrl = async() => {
const response = await axios.get(url)
const response_data = response.data.data
setData(response_data)
if(response_data.length > 11){ // this is better
for(let counter = 0; counter < 12; counter++){
arr.push(<Pretty count={i} question={response_data[i].question} answer_option={response_data[i].option_arr} answer={response_data[i].answer} key={response_data[i]._id} corr_ans={response_data[i]._id}/>)
i+=1
}
let dat = arr.concat(currData)
setCurrData(prevState => {
if(prevState.length === dat.length) {return prevState} else {return dat} // this will avoid the infinite render
})
}
}
fetchFromUrl()
}, [])
NOTE ALSO : you need the await
key only in this line
const response = await axios.get(url)
Upvotes: 1