Keep component scrolled to bottom - reactjs

I have made a mini chat box on an application that sits about mid way down the site on the 3rd section. I'd like to have this chat box always scrolled to the bottom when people type. I am currently using the bellow:
ChatMessage.js
const messagesEndRef = useRef(null)
const scrollToBottom = () => {messagesEndRef.current.scrollIntoView({ behavior: "smooth", block: 'nearest', inline: 'start' })}
useEffect(scrollToBottom, [messageUser]);
return (
<>
<div className='text-left my-2 mx-2'>
<span className={`inline-block pr-4 pl-2 py-2 ${messageClass} rounded-lg`}>
<span className='text-xs'>{username}</span><br />
<span className='text-md font-bold'>{text}</span>
</span>
</div>
<div ref={messagesEndRef} />
</>
)
ChatBox.js
{messages && messages.map(msg => <ChatMessage key={msg.id} messages={msg} user={props.user} /> )}
This solution has an issue when the user is actually not on the chat box page. If the user is to scroll to the top or bottom of the website, each time a message occurs the user if forced up to the chat box. Is there a way that I can have just the chatbox itself scroll to bottom without affecting the users exploring the rest of the site?
I tried thinking of using an iFrame or something but that didn't seem like it would be the best solution.
Thanks in advance.

i think ChatBox component should have be set position: fixed and stay on bottom and user can minimize or expand ChatMessage component every they want chat or not.

Related

How to make database updates and state changes in React show up across all connected pages?

I have a task in hand where I have a page A, where I can drag and drop to reorder certain components displayed as a list and another page B, which simply displays the list to the user without allowing any changes of order, and these two pages are supposed to stay updated with their current state. Any changes on page A should be reflected on page B without having to reload it. I do store my changes in a MongoDB database, and refreshing page B shows the updated order. And I know I can make the page update without refreshing it by simply making the page itself check after each x second the current condition of the database, but that feels resource heavy. Is there a better way to do this?
This is the fragment where I need the changes to happen. dragAndDrop is a prop item that is true on page A but false on page B.
<React.Fragment>
{
dragAndDrop ?
(
<Draggable draggableId={result.id} index={index}>
{(provided, snapshot) => (
<div
className={snapshot.isDragging ? "result-card dragging" : "result-card"}
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div className="d-flex align-items-center">
<span className="math-result">= { result.result }</span>
<span className="calculation-title">{ result.title }</span>
<button className="cstm-btn-red" onClick={() => this.openModal()}>See Input</button>
<Modal open={this.state.isOpen} onClose={() => this.closeModal()}>
{ result.inputContent }
</Modal>
</div>
</div>
)}
</Draggable>
) :
(
<div className="result-card">
<div className="d-flex align-items-center">
<span className="math-result">= { result.result }</span>
<span className="calculation-title">{ result.title }</span>
<button className="cstm-btn-red" onClick={() => this.openModal()}>See Input</button>
<Modal open={this.state.isOpen} onClose={() => this.closeModal()}>
{ result.inputContent }
</Modal>
</div>
</div>
)
}
</React.Fragment>
I'm still rather fresh to React JS and am learning more and more each day. I feel like there should be a discussion regarding my issue somewhere out there.
But I have been unable to find it. So, sorry for the post probably being a duplicate.
Simple way to store all the updates is to use Redux or Context API or the local storage of browser, you will have to go the links given to understand more. Basically, they store all the changes user is making without reloading any pages and it will persist till the user closes the tab.
If you want to store them permanently, I recommend calling the API ONCE he gets OUT of the page A ( you will have to track the page URLs or use useEffect return function to call this API - these seem difficult to understand first for a beginner but once you understand the useEffect hooks or react-router hooks, its very easy to do this)
and store his order in DB but also simultaneously update the redux state or context API state or local storage. Normally, we use redux for this which gives lot of advantages compared to Context or local storage.

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

Too much blank space under each card, using reactjs-social-embed

I am making a webpage using react where I want to display every post in a facebook page. I am using this package to display each post and Facebook graph API to get each postID then I map it.
https://www.npmjs.com/package/reactjs-social-embed
My problem is that there is just too much blank space under each facebook post(See img). Id like each post to be positioned right on top of eachother.
If I try to change the height to auto or 100% the Like btn, comment, and share btn disappears.
return (
<>
{fbData.map((post) => (
<div style={{paddingTop: 40}}
className="col-lg-5 col-md-5 col-sm-5 container justify-content-center">
<Row>
<Facebook type="post"
width="800px"
height="680px"
url={`https://www.facebook.com/102417811874407/posts/${post.id.split("_")[1]}`} />
</Row>
</div>
)
)}
</>
);
};
export default Nyheter;
The facebook API does not return img size either :/
This is how it looks if I try to change each post to 200px

How to use react-swipe to render many items within one slide?

I am using React-swipe for a project. I follow the main example.
<div>
<ReactSwipe
className="carousel"
swipeOptions={{ continuous: false }}
ref={el => (reactSwipeEl = el)}
>
<div>PANE 1</div>
<div>PANE 2</div>
<div>PANE 3</div>
</ReactSwipe>
<button onClick={() => reactSwipeEl.next()}>Next</button>
<button onClick={() => reactSwipeEl.prev()}>Previous</button>
</div>
But the result is that PANE1, PANE2, PANE3 all takes up the whole screen width. I want all PANE1, PANE2 and PANE3 have 60vw so that you see PANE1 and part of PANE2. What I want is Facebook like mobile carousel which is somehow like the following:
https://codesandbox.io/s/lrk6955l79?module=%2Fsrc%2FCarousel.js
Thank you.
In src/components, change flex-basis property of CarouselSlot from 80% to something like 50%. And if you want to change the starting point of the visible slides, you can play with transform property of CarouselContainer.

Carousel in ReactJS using ReactAnimationGroup

I am trying to create a scrolling carousel, similar to bootstrap's carousel, using pure React and inline styles.
I'm having a lot of trouble figuring out how state should be.
Here is the relevant code:
Parent component:
customers.jsx
<button style={{zIndex: 100}} onClick={() => this.renderPrev()}>Prev</button>
<ReactTransitionGroup transitionName="example">
{_.map(customers, (customer, i) => {
if (this.state.selected === i){
return <Customer
key={customer.name}
customer={customer}
selected={this.state.selected}
idx={i}
moving={this.state.moving}
toggle={()=>this.toggle()}
/>
} else {
return null
}
})
}
</ReactTransitionGroup>
<button style={{zIndex: 100}} onClick={() => this.renderNext()}>Next</button>
renderPrev/renderNext are simply functions that checks to see if the current selected customer is the first or last one, and if it is, then loop around.
Child component
customer.jsx
render() {
<div style={_.assign({},styles.root, position)}>
<div style={{verticalAlign: 'middle'}} >
<img style={styles.image} className="img-circle img-responsive" width="200px" src={this.props.customer.image}/>
<img style={styles.logo} className="img-responsive" src={this.props.customer.logo}/>
<h3 style={{color: '#F05A28', margin: 0,}}>{this.props.customer.name}</h3>
<h4 style={{fontWeight: 200, margin: 0,}}>{this.props.customer.title}</h4>
<p style={{fontSize: 16}}>{this.props.customer.description}</p>
</div>
<button onClick={()=>this.props.toggle()}>Click</button>
</div>
}
I'm able to get carousel to work, but it's static. Ideally, I want the customers to slide left/right depending on if it's going to the next or previous customer.
My attempted solution was to try to send new props into the current customer when the next button is pressed, but the current customer never receives those new props because it's not even rendered due to the conditional.
I think the main problem is that only one customer is rendering at a time due to the condition within the map, and that customer does not get the index of the next customer.
Can someone guide me in the right direction?
I know there's React Slick Carousel but I wasn't able to get it to work, so I wanted to try my hand at doing it myself.

Resources