Reputation: 177
I am new to javascript and react. I am trying to figure out why blockHeight state variable is not accessible inside the loadNewBlocks function which triggers when the user scrolls.
Current value of blockHeight is 0 but I am expecting this value which is set in setBlockHeight(data[data.length - 1].Height); in side useEffect. For e.g. value set inside the setBlockHeight is 14789 so I am expecting 14789 inside loadNewBlocks function.
import { useState, useEffect } from "react";
import connect from "../../Backend/database/dbtest";
export default function test({ data }) {
const [blocks, setBlocks] = useState([]);
const [blockHeight, setBlockHeight] = useState(0);
console.log("top block height: ", blockHeight);
const loadNewBlocks = async () => {
console.log(
`Value in loadNewBlocks http://localhost:3000/api/fetchBlocks?blockHeight=${blockHeight}`
);
const res = await fetch(
`http://localhost:3000/api/fetchBlocks?blockHeight=${blockHeight}`
);
if (!res.ok) {
console.log("Error in fetching blocks");
return;
}
const newBlocks = await res.json();
setBlockHeight(newBlocks[newBlocks.length - 1].Height);
setBlocks((prevBlocks) => [...prevBlocks, ...newBlocks]);
};
// Load Data on Scroll
const handleScroll = async (e) => {
if (
e.target.documentElement.scrollTop + window.innerHeight >=
e.target.documentElement.scrollHeight
) {
loadNewBlocks();
}
};
useEffect(() => {
setBlocks(data);
setBlockHeight(data[data.length - 1].Height);
console.log("useEffect blockHeight", blockHeight);
}, [data]);
useEffect(() => {
window.addEventListener("scroll", handleScroll);
}, []);
return (
<div>
<button className="border-2 bg-red-400"> Submit </button>
{blocks.map((block) => (
<div key={block.blockHeader.blockhash}>
{block.blockHeader.blockhash}
</div>
))}
</div>
);
}
export async function getServerSideProps() {
const connection = await connect();
const res = await fetch("http://localhost:3000/api/fetchBlocks");
const data = await res.json();
return {
props: { data },
};
}
Here is the updated solution. Used useRef to maintain the value.
import Link from "next/link";
import connect from "../../Backend/database/dbtest";
import { useEffect, useState, useRef, useCallback } from "react";
// import read from "../../Backend/database/read";
export default function Blocks({ data }) {
const [blocks, setBlocks] = useState([]);
const HeightRef = useRef();
const isLoading = useRef(false);
const MINUTE_MS = 500000;
const loadNewBlocks = async () => {
if (!isLoading.current) {
isLoading.current = true;
console.log(
`http://localhost:3000/api/fetchBlocks?blockHeight=${HeightRef.current}`
);
const res = await fetch(
`http://localhost:3000/api/fetchBlocks?blockHeight=${HeightRef.current}`
);
const newBlocks = await res.json();
console.log("New Blocks: ", newBlocks);
HeightRef.current = newBlocks[newBlocks.length - 1].Height;
console.log("New Height: ", HeightRef.current);
setBlocks((prevBlocks) => [...new Set([...prevBlocks, ...newBlocks])]);
isLoading.current = false;
}
};
const handleScroll = async (e) => {
if (
e.target.documentElement.scrollTop + window.innerHeight >=
e.target.documentElement.scrollHeight
) {
await loadNewBlocks();
}
};
useEffect(() => {
setBlocks(data);
HeightRef.current = data[data.length - 1].Height;
window.addEventListener("scroll", handleScroll);
}, []);
return (
<div className="bg-black flex justify-center pt-[2em]">
<div className="w-full h-full bg-gradient-to-r from-indigo-700 to-sky-600 rounded-2xl text-white grid grid-rows-[4em_1fr] mx-[6em]">
<div className=" text-4xl font-bold pl-[1em] pt-[1em]">
Latest Blocks
</div>
<div className="pt-[2em]">
<div className="grid grid-cols-[1fr_3fr_1fr_1fr] font-bold h-[3em] text-xl border-b-2">
<div className="flex justify-center"> Block Height </div>
<div className="flex justify-center">Block Header</div>
<div className="flex justify-center"> Transactions </div>
<div className="flex justify-center"> Block Size </div>
</div>
{blocks.map((block) => (
<div
key={block.blockHeader.blockhash}
className="cursor-pointer grid grid-cols-[1fr_3fr_1fr_1fr] border-b-[1px] h-[4em] pt-[1em] hover:bg-gradient-to-r from-purple-600 to-blue-400 rounded-2xl"
>
<div className="flex justify-center"> {block.Height} </div>
<div className=" ">
<Link href={`/block?blockhash=` + block.blockHeader.blockhash}>
<div className="flex justify-start px-[2em]">
{block.blockHeader.blockhash}
</div>
</Link>
</div>
<div className="flex justify-center"> {block.TxCount} </div>
<div className="flex justify-center"> {block.BlockSize} </div>
</div>
))}
</div>
</div>
</div>
);
}
export async function getServerSideProps() {
const connection = await connect();
// const blocks = JSON.parse(JSON.stringify(await read.main(false, false, 20)));
const res = await fetch("http://localhost:3000/api/fetchBlocks");
const data = await res.json();
return {
props: { data },
};
}
Upvotes: 0
Views: 61
Reputation: 416
To try to bring
useEffect(() => {
window.addEventListener("scroll", handleScroll);
- setBlocks(data);
- setBlockHeight(data[data.length - 1].Height);
}, []);
change to
useEffect(() => {
setBlocks(data);
setBlockHeight(data[data.length - 1].Height);
}, [data]);
useEffect(() => {
window.addEventListener("scroll", handleScroll);
}, []);
Make sure that only one thing is doing
By the way, a better approach would be to throttle your scrolling function you can use the lodash throttle method
So, I expect you to do this to maintain application optimization
const MAX_TIMES = 300
const handleScroll = () => {}
useEffect(() => {
const throttleScroll = throttle(handleScroll, MAX_TIMES);
window.addEventListener('scroll', throttleScroll);
return () => {
window.removeEventListener('scroll', throttleScroll)
}
}, [])
Good Luck :)
Upvotes: 1