Carousel in ReactJS using ReactAnimationGroup - reactjs

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.

Related

Keep component scrolled to bottom

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.

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.

Why react-frame-component iframe's body becomes empty?

Imagine, rendering multiple iframes (using react-frame-component) and allowing users to reorder them.
Surprisingly, when iframes are reordered, the <body> of one of them becomes empty.
I raised an issue here, but wonder maybe someone here would be able to assist as well since there is no much activity on the repo lately.
function App() {
const [frames, setFrames] = useState(["first", "second"]);
return (
<div className="app">
<div className="framesContainer">
{frames.map(frame => (
<div className="frame" key={frame}>
<Frame style={{ width: 200, height: 200 }}>
<h1>Hello World</h1>
</Frame>
<div>{frame}</div>
</div>
))}
</div>
<div className="actions">
<button
onClick={() => {
setFrames(frames => [frames[1], frames[0]]);
}}
>
Swap frames
</button>
</div>
</div>
);
}
After clicking the button, first iframe's <body> becomes empty.
CodeSandbox
I face the same issue when using react-dnd / react-beautiful-dnd to do multiple iframe reordering and sorting.
The only method I found is to force the iframe component to rerender when the orders state update. However, the app could be extremely slow when all iframe update at once.

How to route to a page with specific card details when clicking on a card?

My cards have the info coming from a JSON file. Cards are all rendering properly, but I want to add an onClick function to each card rendered to reroute to another page I have called paintingInfo.js. In this paintingInfo file I want to display the image from the JSON file as well as the description. Can someone please help me out, relatively new to React.
class Paintings extends Component {
state = {
cardInfo: [...cardInfo]
};
render() {
return (
<React.Fragment>
<Navbar className="navCustom d-flex justify-space-between" bg="light" variant="light">
<Navbar.Brand href="/">SNR Arts</Navbar.Brand>
<Nav className="ml-auto navCust">
<Nav.Link href="/">Home</Nav.Link>
<Nav.Link href="/paintings">Paintings</Nav.Link>
<Nav.Link href="/contact">Contact</Nav.Link>
</Nav>
</Navbar>
<div className="container-fluid">
<div className="row align-items-center justify-content-between">
{/* print out cards here */}
{this.state.cardInfo.map(card => {
return (
<div className="col-12 col-sm-3 col-md-2 my-3" key={card.id}>
<img
src={card.image}
alt={card.name}
className="img-fluid img-thumbnail rounded indvCard bg-dark"
/>
</div>
);
})}
</div>
</div>
My first thought to do this in a simple way that doesn't require a major overhaul would be to define a method inside of the class called moreInfo(id).
Then in the .map inside the render, just like you are giving the image src, alt, and className attributes, you can give it onClick={this.moreInfo(card.id}}. I'm not 100% sure if this will work but I feel pretty confident that it would.
The way that I would tend to build this personally would be to make the stuff inside the return statement of the .map and make a component out of it. So it would be
{this.state.cardInfo.map(card => (
<CardComponent
props
props
props
props />
))}
Edit: On my second read-through, I realized that I didn't give any actual render logic. My thought on that half of the question would be to render the moreInfo inside this same component. Keep a boolean in your state to track whether more info has been expanded or not. Put a ternary operator in the render() method that references that boolean. Put the current contents of your render method on one side of the ternary, and have the other side display additional info.
2nd edit: adding code block for proposed .map function, some of it didn't show up in display because of the markup.

How to change the background image with react-motion and loop through a bunch of images?

I am using react-motion to loop through a bunch of images. I'm trying to make the background change programmatically after a certain amount of time.
The component render should be something like this. Motion and spring are from 'react-motion' package. Checkout the code for the photo demo for more details.
<Motion style={{height: spring(currHeight), width: spring(currWidth)}}>
{container =>
<div className="demo4-inner" style={container}>
{configs.map((style, i) =>
<Motion key={i} style={style}>
{style =>
<img className="demo4-photo" src={`./${i}.jpg`} style={style} />
}
</Motion>
)}
</div>
}
</Motion>

Resources