Scroll to the bottom of a scrollable div in react - javascript

I've tried numerous solutions to try scroll to the bottom of a div as at the bottom user feedback can be found on whether their registration form successfully submitted.
var objDiv = document.getElementById("form");
objDiv.scrollTop = objDiv.scrollHeight;
and
window.scrollTo(0,document.body.scrollHeight);
and
window.scrollTo(0,document.querySelector("#form").scrollHeight);
With no success
Here's the react code for the form
return (
<div
className={styles.register_container}
id="register-container"
style={{
height: "100%",
overflow: "scroll",
}}
>
<HomeIcon />
<div className={styles.login_button_container}>
<p>Already have an account? </p>
<button
onClick={() => {
router.push("/login");
}}
>
Log in
</button>
</div>
<div
style={{
padding: "60px 0",
height: "100%",
maxWidth: "300px",
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
id="form"
>
<img
src="/assets/Logo/ROA_logowhite.png"
style={{
height: "100px",
maxWidth: "100px",
}}
onClick={() => {
var objDiv = document.getElementById("form");
objDiv.scrollTop = objDiv.scrollHeight;
}}
/>
{page === 2 && (
<div style={{ width: "100%" }}>
<button className="back-button" onClick={backButtonHandler}>
<FontAwesomeIcon icon={faAngleLeft} />
Back
</button>
</div>
)}
{page === 1 && loginDetails}
{page === 2 && personalDetails}
<div style={{ width: "100%", padding: "5px 0" }}>
<button
className="form-button"
onClick={buttonHandler}
style={{ minHeight: "50px" }}
>
{submitButton}
</button>
</div>
{loading && (
<div
style={{
padding: "5px",
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<ReactLoading
type="spin"
color="#1dd760"
height={50}
width={50}
id="loader"
/>
</div>
)}
{registrationError && (
<p className="form-submit-error">
Registration error, refresh your page and try again
</p>
)}
{true && (
<div>
<p
style={{ marginBottom: "10px" }}
className="form-submit"
id="submit"
>
Redirecting to login ... You should receive a welcome email, if
not please try registering again or visit the{" "}
<a href="/contact" style={{ color: "#1dd760" }}>
contact
</a>{" "}
page.
</p>
</div>
)}
</div>
</div>
);
I can't directly focus on the submit success message as setState is asynchronous in react. Just need a function that allows me to scroll the bottom of the div when the next/submit button is clicked

The proper way to access/modify DOM elements in React function components is to use the useRef hook.
https://reactjs.org/docs/hooks-reference.html#useref
Here is an example how you can solve your problem:
import * as React from "react";
const Component: React.FunctionComponent = () => {
const ref = React.useRef<HTMLDivElement>(null);
const [success, updateSuccess] = React.useState(false);
const buttonHandler = () => {
updateSuccess(true);
if (ref.current) {
const offsetBottom = ref.current.offsetTop + ref.current.offsetHeight;
window.scrollTo({ top: offsetBottom });
}
};
return (
<div>
...
<button onClick={buttonHandler}>Scroll</button>
{success ? (
<div
ref={ref}
style={{ height: "2000px", display: !success && "none" }}
>
Long Success Message
</div>
) : null}
</div>
);
};
export default Component;

Related

Ionic Elements lost their original position when the page decreases its size

On this StackBlitz project: https://stackblitz.com/edit/ionic-react-demo-s368kk?file=App.jsx
I have the following code:
import React from 'react';
import { IonPage, IonContent, IonRow } from '#ionic/react';
const Button = ({ children }) => (
<div
style={{
display: 'inline-block',
backgroundColor: '#fff',
padding: '12px 22px',
margin: '10px 10px',
}}
>
<span>{children}</span>
</div>
);
const OptionsButtons = () => (
<div style={{ textAlign: 'center' }}>
<div>
<Button>This is your Option Number 1</Button>
</div>
<div>
<Button>This is your Option Number 2</Button>
</div>
</div>
);
const Delimiter = () => (
<div>
<span style={{ color: '#ff0' }}>==============================</span>
</div>
);
const App = () => (
<IonPage>
<IonContent
fullscreen
className=""
style={{
'--ion-background-color': 'none',
backgroundImage: `url('https://wallpaperaccess.com/full/1902544.jpg')`,
backgroundPosition: 'center',
backgroundSize: 'cover',
}}
>
<IonRow
style={{
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<OptionsButtons />
<Delimiter />
<OptionsButtons />
<Delimiter />
<OptionsButtons />
<Delimiter />
<OptionsButtons />
</IonRow>
</IonContent>
</IonPage>
);
export default App;
Normally the page looks like on the image below when it has enough space:
Note that the elements are vertically aligned (which is a requirement for me).
But if I decrease the viewport size, then the elmements get reorganized around and lost their initial position as you can see on the image below:
I really need the elements to keep their original position as when they had enough space. It doesn't matter if the user has to scroll down in order to see the elements beyond the fold. But remember that when there is enough space, I need the elements to be vertically aligned.
Any idea on how to solve this?
If you want you can post your forked StackBlitz.
Thanks!
IonRow elements are meant to be used inside IonGrid. Outside of that, it might show buggy behaviour. try this:
import React from 'react';
import { IonPage, IonContent, IonRow, IonGrid } from '#ionic/react';
const Button = ({ children }) => (
<div
style={{
display: 'inline-block',
backgroundColor: '#fff',
padding: '12px 22px',
margin: '10px 10px',
}}
>
<span>{children}</span>
</div>
);
const OptionsButtons = () => (
<div style={{ textAlign: 'center' }}>
<div>
<Button>This is your Option Number 1</Button>
</div>
<div>
<Button>This is your Option Number 2</Button>
</div>
</div>
);
const Delimiter = () => (
<div>
<span style={{ color: '#ff0' }}>==============================</span>
</div>
);
const App = () => (
<IonPage>
<IonContent
fullscreen
className=""
style={{
'--ion-background-color': 'none',
backgroundImage: `url('https://wallpaperaccess.com/full/1902544.jpg')`,
backgroundPosition: 'center',
backgroundSize: 'cover',
}}
>
<IonGrid>
<IonRow
style={{
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<OptionsButtons />
<Delimiter />
<OptionsButtons />
<Delimiter />
<OptionsButtons />
<Delimiter />
<OptionsButtons />
</IonRow>
</IonGrid>
</IonContent>
</IonPage>
);
export default App;
also, not using IonCol might cause some bugs as well, I'd suggest not using ionic grid system in this case or using it like this:
<IonGrid style={{
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}>
<IonRow>
<IonCol>
<OptionsButtons />
<Delimiter />
</IonCol>
</IonRow>
<IonRow>
<IonCol>
<OptionsButtons />
<Delimiter />
</IonCol>
</IonRow>
<IonRow>
<IonCol>
<OptionsButtons />
<Delimiter />
</IonCol>
</IonRow>
</IonGrid>

Select only a card at a time on click in reactjs

I have a react component which has some cards, When I click the plus icon in the card, it would expand and show some data for 30sec and then the data will disappear and on click it will reappear again, here is the component
import React from "react";
import { FaPlus } from "react-icons/fa";
import useTimeout from "../../../common/useTimeout";
import { Modal } from "../../../common/Modal";
import { ToggleState } from "../../../common/Toggle";
import { BsSearch } from "react-icons/bs";
import AdvancedFilter from "./AdvancedFilter";
export default function CitiesList({ cities }: { cities: any }): JSX.Element {
const [filter, setFilter] = React.useState("");
const [sortType, setSortType] = React.useState("");
const [selectedCity, setSelectedCity] = React.useState<any | null>(null);
console.log(filter);
const sorted = cities.sort((a: { name: string }, b: { name: any }) => {
const isReversed = sortType === "asc" ? 1 : -1;
return isReversed * a.name.localeCompare(b.name);
});
const onSort = (sortType: React.SetStateAction<string>) => {
console.log("changed");
setSortType(sortType);
};
const [showMeta, setShowMeta] = React.useState(false);
const handleClick = () => setShowMeta(true);
const getSelectedCity = (selectedCity: any) => {
setSelectedCity(selectedCity);
console.log("SELECTED CITY", selectedCity);
};
const [visible, setVisible] = React.useState(true);
const hide = () => setVisible(false);
useTimeout(hide, 30000);
console.log("CITIES", cities);
console.log({ selectedCity });
return (
<div style={{ marginTop: "3rem" }}>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "20px",
}}
>
<div>List of cities</div>
<div style={{ display: "flex", alignItems: "center" }}>
<div style={{ marginRight: "1rem" }}>
<ToggleState
render={({ isOpen, open, close }) => {
return (
<>
<button
type="button"
className="btn btn-primary"
onClick={() => {
isOpen ? close() : open();
}}
>
Advanced Filter
</button>
<Modal
isActive={isOpen}
modalContentWidth={"30%"}
header={() => "Advanced Filter"}
close={() => close()}
renderBody={() => {
return <AdvancedFilter close={() => close()} />;
}}
></Modal>
</>
);
}}
/>
</div>
<div style={{ position: "relative", marginRight: "1rem" }}>
<input
type="text"
placeholder="Filter"
name="namePrefix"
style={{ padding: "0.35rem" }}
onChange={(e: any) => {
setFilter(e.target.value);
}}
/>
<div style={{ position: "absolute", top: "5px", right: "5px" }}>
<BsSearch size="16" />
</div>
</div>
<div style={{ width: "8rem" }}>
<div className="btn-group">
<button
type="button"
className="btn dropdown-toggle sort-button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{sortType === "asc"
? "Ascending"
: sortType === "desc"
? "Descending"
: "Select"}
</button>
<ul className="dropdown-menu sort-button">
<li>
<button
className="dropdown-item"
type="button"
onClick={() => onSort("asc")}
>
Ascending
</button>
</li>
<li>
<button
className="dropdown-item"
type="button"
onClick={() => onSort("desc")}
>
Descending
</button>
</li>
</ul>
</div>
</div>
</div>
</div>
<div>
<div>
<div className="row">
{cities &&
sorted.map((item: any, index: number) => (
<div className="col-lg-3" key={index}>
<div
className="card"
style={{
textAlign: "center",
display: "flex",
justifyContent: "center",
paddingBottom: "1rem",
marginBottom: "1rem",
marginRight: "1rem",
}}
>
<div className="card-body">
<h5 className="card-title">{item.name}</h5>
</div>
{visible && showMeta ? (
<div>
<p>Longitude: {item.longitude}</p>
<p>Latitude: {item.latitude}</p>
<p>Population: {item.population}</p>
{/* <p>Time Zone: America</p> */}
</div>
) : (
<div
onClick={() => {
handleClick();
getSelectedCity(item.id);
}}
style={{ cursor: "pointer" }}
>
<FaPlus size="18" />
</div>
)}
</div>
</div>
))}
</div>
</div>
</div>
<div
style={{ marginTop: "30px", display: "flex", justifyContent: "center" }}
>
{cities && cities.length > 10 ? (
<button className="secondary-button">Load More</button>
) : (
<p>There are no more cities</p>
)}
</div>
</div>
);
}
here is the useTimeout function
import { useEffect, useRef } from "react";
function useTimeout(callback: () => void, delay: number | null) {
const savedCallback = useRef(callback);
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
if (delay === null) {
return;
}
const id = setTimeout(() => savedCallback.current(), delay);
return () => clearTimeout(id);
}, [delay]);
}
export default useTimeout;
Now currently if I click on one card, all the cards opens and also after when the data disappears after 30sec it does not reappear on button click. I need to reload the page to do reappear data again.I need to solve 2 issues here: 1. how can I open one card only at a time on clicking on the icon, 2. how can I reappear data on button click without refreshing the page.
As I understand you, some information is
<p>Longitude: {item.longitude}</p>
<p>Latitude: {item.latitude}</p>
<p>Population: {item.population}</p>
You have global statement of showing this info for all cards. To reduce it, make new component which will have local state of this info:
import React from 'react'
const timeout = 15000
export const CityCard = ({item, visible, getSelectedCity}) => {
const [showMeta, setShowMeta] = React.useState(false)
const handleClick = React.useCallback(()=>{
setShowMeta(true)
setTimeout(()=>{
setShowMeta(false)
},timeout )
}, [showMeta])
return(
<div className="col-lg-3" key={index}>
<div
className="card"
style={{
textAlign: "center",
display: "flex",
justifyContent: "center",
paddingBottom: "1rem",
marginBottom: "1rem",
marginRight: "1rem",
}}
>
<div className="card-body">
<h5 className="card-title">{item.name}</h5>
</div>
{visible && showMeta ? (
<div>
<p>Longitude: {item.longitude}</p>
<p>Latitude: {item.latitude}</p>
<p>Population: {item.population}</p>
{/* <p>Time Zone: America</p> */}
</div>
) : (
<button
onClick={() => {
handleClick();
getSelectedCity(item.id);
}}
type='button'
disabled={showMeta}
style={{ cursor: "pointer" }}
>
<FaPlus size="18" />
</button>
)}
</div>
</div>
)
}
At the end, add this component to the CityList

How to create a custom button in react-pdf-viewer?

I'm using react-pdf-viewer in a React application and need to customise the button images to suit the style of the app. I can get the viewer to display the correct button style but the button then does not do anything when it is clicked, nor does it display the tooltip when hovered over. I've tried attaching onClick functions to the various elements of the button but they only fire on rendering and not when clicked.
This is the main code for the viewer; I'm first trying to get the download button to work and will then use the solution for the other buttons.
import { Viewer, Worker } from '#react-pdf-viewer/core';
import { defaultLayoutPlugin } from '#react-pdf-viewer/default-layout';
import { zoomPlugin } from '#react-pdf-viewer/zoom';
import { getFilePlugin } from '#react-pdf-viewer/get-file';
import { DownloadButton } from './Components/Buttons';
import '#react-pdf-viewer/core/lib/styles/index.css';
import '#react-pdf-viewer/default-layout/lib/styles/index.css';
import '#react-pdf-viewer/toolbar/lib/styles/index.css';
const App = () => {
const zoomPluginInstance = zoomPlugin();
const { ZoomPopover } = zoomPluginInstance;
const getFilePluginInstance = getFilePlugin();
const { Download } = getFilePluginInstance;
const renderToolbar = (Toolbar) => (
<Toolbar>
{(slots) => {
const { NumberOfPages, CurrentPageInput, ZoomIn, ZoomOut, Print } = slots;
return (
<div
style={{
alignItems: 'center',
display: 'flex',
justifyContent: 'space-between',
marginRight: 40
}}
>
<div style={{display: 'flex', alignItems: 'center'}}>
<div style={{ padding: '0px 5px' }}>
<CurrentPageInput style={{fontSize: 16}} />
</div>
<div style={{ padding: '0px 5px 3px' }}>
/ <NumberOfPages /> pages
</div>
</div>
<div className="zoomControls" style={{display: 'flex', alignItems: 'center'}}>
<div style={{ padding: '0px 5px' }}>
<ZoomOut />
</div>
<div style={{ padding: '0px 5px', backgroundColor: '#fff', borderRadius: 4 }}>
<ZoomPopover />
</div>
<div style={{ padding: '0px 5px' }}>
<ZoomIn />
</div>
</div>
<div style={{display: 'flex', alignItems: 'center'}}>
<div style={{ padding: '0px 5px', marginLeft: 'auto' }}>
<Print />
</div>
<div style={{ padding: '0px 5px' }}>
<Download>
{() => (
<DownloadButton />
)}
</Download>
</div>
</div>
</div>
);
}}
</Toolbar>
);
const defaultLayoutPluginInstance = defaultLayoutPlugin({
renderToolbar,
sidebarTabs: (defaultTabs) => [defaultTabs[0]],
});
return (
<Worker workerUrl="https://unpkg.com/pdfjs-dist#2.9.359/build/pdf.worker.js">
<div className="pdfContainer">
<Viewer
fileUrl={'https://file-examples-com.github.io/uploads/2017/10/file-example_PDF_1MB.pdf'}
plugins={[defaultLayoutPluginInstance, zoomPluginInstance, getFilePluginInstance]}
/>
</div>
</Worker>
);
};
export default App;
and this is the imported download button
export const DownloadButton = () => (
<button className="downloadButton" aria-label="Download">
<img src={process.env.PUBLIC_URL + '/icons/download.svg'} className="btButton" alt="Download" />
</button>
);
As far as the downloading the file, it seems that you've forgotten to use the props of the download button.
What you need to do is add the props and then pass the onClick handler to the DownloadButton like so:
<Download>
{(props) => (
<DownloadButton onCLick={props.onClick} />
)}
</Download>
Since your DownloadButton is a wrapper around a button you also need to define onClick as a prop there and then pass it down to the HTML button element.
/**
* A button used to download the a PDF.
*
* #param {Object} [props]
* #param {*} [props.onClick] The #react-pdf-viewer/get-file click handler.
*/
export const DownloadButton = (props) => {
return (
/** Pass the download button's `onClick` handler to this button. */
<button
onClick={props.onClick}
className="downloadButton"
aria-label="Download"
>
<img
src={process.env.PUBLIC_URL + "/icons/download.svg"}
className="btButton"
alt="Download"
/>
</button>
);
};
As far as the tooltip goes, it seems that you'll have to implement that yourself unless you use the default DownloadButton provided by `#react-pdf-viewer/get-file.

React - how to apply local storage for hook value

I use the react-range package for personal purposes of my project, the problem is that I cannot save the value when the page is refreshed, I tried to use the local storage but I could not
As you understand, I need to save the value using local storage, in addition, I will leave a link to mine on codesandbox link
SideBarBlurChange.jsx
import React, {useEffect, useState} from "react";
import {getTrackBackground, Range} from "react-range";
const STEP = 0.1;
const MIN = 0;
const MAX = 100;
export default function SideBarBlurChange(props) {
const [values, SetValues] = useState([20])
const SaveChanges = () => {
alert(values)
}
return (
<>
<div
style={{
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
}}
>
<Range
values={values}
step={STEP}
min={MIN}
max={MAX}
onChange={(values) => SetValues(values)}
renderTrack={({ props, children }) => (
<div
onMouseDown={props.onMouseDown}
onTouchStart={props.onTouchStart}
style={{
...props.style,
height: "36px",
display: "flex",
width: "100%"
}}
>
<div
ref={props.ref}
style={{
height: "5px",
width: "100%",
borderRadius: "4px",
background: getTrackBackground({
values: values,
colors: ["#548BF4", "#ccc"],
min: MIN,
max: MAX
}),
alignSelf: "center"
}}
>
{children}
</div>
</div>
)}
renderThumb={({ props, isDragged }) => (
<div
{...props}
style={{
...props.style,
height: "42px",
width: "42px",
borderRadius: "4px",
backgroundColor: "#FFF",
display: "flex",
justifyContent: "center",
alignItems: "center",
boxShadow: "0px 2px 6px #AAA"
}}
>
<div
style={{
height: "16px",
width: "5px",
backgroundColor: isDragged ? "#548BF4" : "#CCC"
}}
/>
</div>
)}
/>
<output style={{ marginTop: "30px" }} id="output">
{values[0].toFixed(1)}
</output>
<button onClick={() => SaveChanges()}>Save</button>
</div>
</>
);
}
I think your main problem was that localStorage doesn't store anything besides strings. You're going to want to parseInt then check to make sure localStorage isn't null. Can you try this and see if it works?
const ls = parseInt(window.localStorage.getItem('values'));
const [values, SetValues] = useState(ls ? [ls] : [20]);
const SaveChanges = () => {
alert(values);
localStorage.setItem('values', values);
}

Javascript array slicing based on filter

I'm stuck on writing out logic that will show more comments if user clicks show more comments.
How would i go about performing this logic that filters based on the following: initially there are 2 comments that show(out of 7 total comments). I want to break this down as user keeps clicking on show more. Should show 5 more comments, 3 more comments, 1 more comment, until there is no more comments.
I'm not too sure on what im doing.
CommentList.tsx
import React, { Fragment, useState } from "react";
import Grid from "#material-ui/core/Grid";
import List from "#material-ui/core/List";
import Typography from "#material-ui/core/Typography";
import CommentItem from "./../commentItem/CommentItem";
import moment from "moment";
import OurLink from "../../../common/OurLink";
import OurSecondaryButton from "../../../common/OurSecondaryButton";
import OurModal from "../../../common/OurModal";
const ourStyle = {
backgroundColor: "#FAFAFA",
border: "1px solid #f2f2f2",
borderRadius: "4px",
padding: "15px 20px",
margin: "15px",
};
function CommentList(props: any) {
const [showMore, setShowMore] = useState<Number>(2);
const [openModal, setOpenModal] = useState(false);
const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
const lastIndexOfComments = props.comments.length - 1;
const startIndex = 0;
console.log(lastIndexOfComments);
const showComments = (e) => {
e.preventDefault();
const subtract = props.comments.length - 2 ;
console.log("testing", subtract);
setShowMore(subtract);
// setShowLessFlag(true);
};
const handleClickOpen = () => {
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
};
.....
const showMoreComments = () => {
return props.comments
.slice(startIndex, showMore)
.sort((a, b) => a.id - b.id)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ cursor: "pointer", fontSize: "12px", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
</span>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
));
};
const ourComments = props.comments;
console.log("before comments", ourComments);
console.log("fsfsfsftestingcomments", ourComments.slice(0, showMore));
return (
<Grid>
<Fragment>
<div style={{ margin: "30px 0px" }}>
<OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
View More Comments
</OurSecondaryButton>
</div>
</Fragment>
{showLessFlag === true ? (
// will show most recent comments below
showMoreComments()
) : (
<Fragment>
{/* filter based on first comment */}
{props.comments
.filter((item, i) => item)
.sort((a, b) => b.id - a.id)
.slice(startIndex, showMore)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ fontSize: "12px", cursor: "pointer", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</span>
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
))}
</Fragment>
)}
</Grid>
);
}
// prevents un-necesary re renders
export default React.memo(CommentList);
If you have all comments already fetched, you could simply set a limit and only show the comments with an index lower than the limit.
Check this out: https://stackoverflow.com/a/44071932/10955418

Categories

Resources