React-material-ui-carousel not rendering full-height content on init - reactjs

I am using react-material-ui-carousel v3 with MUI v5. I need to render custom HTML content inside the carousel. The problem I have is that on the first render the first item does not have full height, see images below
return (
<Carousel autoPlay={true}>
{items.map((item, i) => {
const htmlContent = getHtmlContent(decodeHtml(item));
return <div key={i}>{htmlContent}</div>;
})}
</Carousel>
);
First init
After moving to the second page and then to the first page
How can I adjust the height so it shows the full height of the content?

Related

How to do userEvnt.click on a div in react testing library

so i have a component that maps an array and returns a div with an onClick event
{credits?.crew.slice(0, maxCreditsResults).map((crew, idx) => {
return (
<div
className='cast-card'
key={idx}
onClick={() => navigate(`/${EPages.person}/${crew.id}`)}
>
<p>-{crew.name}</p>
<p>Department: {crew.department}</p>
</div>
);
})}
i want to test this click event but i dont know how to get that specific div so i can click it with userEvent.click()
i looked at the methods of the sreen that comes from react testing library but i cant find one that would help me
You can add data-testid like <div data-testid = {idx + '-cast-card' }
Then call first element of div.
const element = screen.getByTestId('0-cast-cart')
fireEvent.click(element);

Image gallery with Ionic React using Ionic-Swipe

My client requested an image gallery feature. Such that I will have an array of images and on clicking each image, I will get like a modal that shows all the images available one by one. I want to achieve this with the Ionic Swiper Component. The example below is for Ionic-Angular, I need Ionic-React.
https://www.youtube.com/watch?v=BGoL0uWRTrY
Is there a way to open the image as a gallery and have zoom, prev and next swipe functionality?
<div className="mt-2">
<IonSlides ref={slideRef} options={slideOpts}>
{bridImages.map((image, idx) => (
<IonSlide key={idx} className="img-container">
<img
src={image.url}
alt={image.alt}
/>
</IonSlide>
))}
</IonSlides>
</div>
Or if there's any other library that is mobile friendly and can also work with Ionic-React, please let me know.
<IonSlides
options={slideOpts}
ref={mySlides}
onIonSlideDidChange={handleSlideChange}
>
list with the event handler and get the swiper object which holds the activeIndex
const handleSlideChange = async () => {
const swiper = await mySlides.current.getSwiper();
console.log("Slide Index", swiper.activeIndex);
// setDisablePrevBtn(swiper.isBeginning);
// setDisableNextBtn(swiper.isEnd);
};
See working project - https://codesandbox.io/s/ionic-react-slides-jq57g
See video describing code and more - https://youtu.be/mCkrZYIbH10

Append components to a fixed list using react-window?

I have a fixed list and grid using react-window, infinite loader, and auto sizer. It's working fine but I'm looking to append a component before the list/grid starts (for example, a search box and a button). What's the correct approach to accomplish this? I want this component to scroll with the fixed list and not scroll separately. I've tired just rendering the component before but then it's not in the fixed list container and doesn't scroll with it.
{/* WANT TO ADD SOME SORT OF COMPONENT HERE SO IT CAN SCROLL WITH LIST */}
{/* CAN'T IN HERE BECAUSE ITS NOT INSIDE THE FIXED CONTAINER SO IT SCROllS SEPARATELY */}
<AutoSizer>
{({ height, width }) => (
<InfiniteLoader
isItemLoaded={index => index < stateData.data.length}
itemCount={stateData.data.length + 1}
loadMoreItems={loadMoreProducts}
>
{({ onItemsRendered, ref }) => (
<FixedSizeList
onItemsRendered={onItemsRendered}
ref={ref}
height={height}
itemCount={stateData.data.length + 1}
itemSize={350}
width={width}
>
{/* WANT TO ADD SOME SORT OF COMPONENT HERE SO IT CAN SCROLL WITH LIST */}
{/* CAN'T IN HERE BECAUSE ITS LOOPING LISTITEM */}
{ListItem}
</FixedSizeList>
)}
</InfiniteLoader>
)}
</AutoSizer>
Edit: Pretty much I don't want the list (or grid) and the actual page to be two different scroll containers. I'd like the whole page to scroll together. I've come across this issue because some of my containers need to have an infinite list of items users can scroll through so the list needed to be virtualized to improve performance.
See a demo here. Really the fixed container should just be considered the whole page and the search box and everything else should scroll with the infinite list. Having two different scroll containers isn't too great for the ux.
If you want the whole page to scroll with your virtual list you will need a window scroller. This also involves playing around with some styling as well. To make your searchbox scroll with your list you will need a position of fixed. A spacer div and some styling helps the illusion.
I added a basic window scroller and some styling changes to your codepen here.
A few options:
Make a wrapper around The autosizer, that holds both your search box and the autosizer.
<>
<SearchBox />
<AutoSizer>
... your items
</AutoSizer>
</>
let the AutoSizer contain both the search and the list
<AutoSizer>
<SearchBox />
<List>
... your items
</List>
</AutoSizer>
Since your infinite scroll is using a render function you might need fragments
<AutoSizer>
<InfiniteScroll>
{({ onItemsRendered, ref }) => (
<>
<SearchBox />
<List>
... your items
</List>
<>
)}
</InfiniteScroll>
</AutoSizer>
Here I edited your example and made it work using this approach.
Please note that the page scrolls only because of the top and bottom bars; which is the behaviour in your example.
Let the infinite loader populate an array, and append an extra item to that. The item can have a certain type. Assuming the FixedSizeList is the List component from react-virtualized then you can use it's rowRenderer to render the item of type "search" differently than the other items. Something like:
function rowRenderer ({ key, type, value, ...rest }) {
if (type === 'search') {
return <Search key={key} placeholder={value} {...rest} />
}
return <div key={key} {...rest}>{value}</div>
}
// Render your list
ReactDOM.render(
<AutoSizer>
{({ height, width }) => (
<List
height={height}
rowCount={list.length}
rowHeight={20}
rowRenderer={rowRenderer}
width={width}
/>
)}
</AutoSizer>,
document.getElementById('example')
);
Perhaps it also helps to look at the simple example from Vaughn.

React how to create custom overflow ellipsis

I would like to create a top navigation with a variable amount of items. All items that don't fit into the bar should not be rendered. There will be a little "..." icon that shows a sub-menu when you hover over it, that display the remaining nav items. Any ideas on how to achieve this? I can't seem to render the nav items conditional to the parents width.
I tried setting a ref on my navigation bar and check the scroll width against the client width but it didn't work. Even if I got it to work, I would still render one item more than I should because I don't know the width of the children beforehand.
<div ref={ref} className="nav-list">
{ref ? items.map(i => {
return ref.scrollWidth <= ref.clientWidth ? (
<div className="nav-item" key={i.id}>
{i.title}
</div>
) : false;
}) : false}
<div className="nav-remaining">
<div>
//render remaining items
</div>
</div>
</div>
I saw someone implementing this by adding the children recursively and then backtrack to remove all children that are overflowing. But I have now idea on how to implement this approach in react.

scrollIntoView doesn't scroll to bottom when there is an image/file in the container

I have a react app that has a commenting section. Users can comment pdfs, images, excel & csv files. When a user opens up a project I want the container with comments to scroll to the very bottom. The functionality works perfectly if the comments are only text. However, when someone adds any sort of file in, it will no longer scroll all the way to the bottom. It only scroll about 3/4 and the more files added, the less it scrolls.
This is where its called:
componentDidUpdate() {
this.scrollToBottom()
}
scrollToBottom(){
this.el.scrollIntoView({ behavior: 'smooth' })
}
This is whats in my render:
<div className="comments-container-parent">
{this.props.projectComments.map((comment) => {
return <ProjectComment editCommentText={this.props.editCommentText} commentId={comment.id} deleteComment={this.props.deleteComment} comment={comment} projectData={this.props.projectData} />
})}
<div style={{ float:"left", clear:"both" }} ref={el => { this.el = el }}></div>
</div>
How can I get the scroll to work properly when files are involved?
I ran into this recently and the solution was to make sure that there is a container (div or whatever) with a fixed height set. Setting the height dynamically or based on some logic in a useEffect hook doesn't work. The height of the images must be set from the start so that when the list renders, the height of the list doesn't change.

Resources