"ScrollView" like component in React JS? - reactjs

I am displaying search results in my app as an unordered list. This works fine when there are like 5 search results, but as soon as I start getting 10-20 results, the list starts growing more and more down the page. I would like to avoid having to scroll down in the entire webpage just to see the contents lower in the list. Is there something like a scroll view where I can define a certain height and then users can scroll inside of the container?
My current code:
class SearchResults extends Component {
render() {
return (
<div style={styles.wrapperDiv}>
<div style={styles.resultsLeft}>
<ul style = {{ listStyleType: "none" }}>
<Result results={this.props.results}/>
</ul>
</div>
<div style={styles.mapRight}>
<GoogleMap/>
</div>
</div>
);
}
}

You can try giving the parent container (wrapperDiv) a height, say 500px and also set overflow-y to be scroll:
<div styles={{ height: '500px', overflowY: 'scroll' }} style={styles.wrapperDiv}>
...
</div>

try this for scroll view on reactJs
https://www.npmjs.com/package/#cantonjs/react-scroll-view

Related

AirBnb two column sticky Mapbox with results scroll - React, Mapbox, Tailwind

I'd like to create the desired results as seen here.
Please view in Desktop widescreen. AirBnb results.
As you can see with the AirBnb results, the Map on the Righthand side sticks perfectly into place while allowing the user to scroll down to view the results on the Lefthand side.
I've been trying to figure out how they have achieved this but am reaching some road blocks. I found some luck with implementing this bit of code but there is still a slight amount of vertical scrolling before the bottom of the map snaps into place. I believe it has to do with the h-screen class making the map height: 100vh
<main className="flex">
{/* Results & Filters section - Left side */}
<section className='flex-grow'>
<div className='lg:inline-flex mt-5 mb-5 space-x-3 text-gray-800 whitespace-no-wrap'>
<p className='custom-button'>Cancellation Flexibility</p>
<p className='custom-button'>Type of Place</p>
<p className='custom-button'>Price</p>
<p className='custom-button'>Rooms and Beds</p>
<p className='custom-button'>More Filters</p>
</div>
<div className="flex flex-col">
{/* Search results */}
{searchResults.map(
({ img, location, title, description, star, price, total }) => (
<InfoCard
key={img}
img={img}
location={location}
title={title}
description={description}
star={star}
price={price}
total={total}
/>
))}
</div>
</section>
{/* Map section - Right side */}
<aside className="hidden h-screen w-[50%] sticky xl:inline-flex l:min-w-[600px] top-0">
<Map searchResults={searchResults} />
</aside>
</main>
Some help would be greatly appreciated. I've started a codesandbox to make it easier to see what I'm experiencing. Please view in Desktop widescreen
https://codesandbox.io/s/determined-bartik-2tftc?file=/pages/index.js
[Edit] : I just noticed the left side is hidden by the map now since the map is out of the flex flow. I'll keep the answer as an idea. If you can manipulate the architecture of the page, it's easy to fix.
Looks like applying :
position: fixed;
right: 0;
justify-content: end;
to the aside tag that contains the map and removing its top-0 class fix your problem. I see that you are using an external library to display the map so I don't know if there is a way to apply css to it since I can't edit the codesandbox sorry. You could just wrap it in a span with a class and target it with .my-class > aside in your css. But first check the documentation, they are probably exposing some classes for you to apply styles.
So I seemed to have solved this. Took a bit of work but I achieved the result I was looking for.
I added some root css here in globals.css file
:root {
--navigation-bar-offset: 90px;
--gp-placement-max-height: calc(100vh - var(--navigation-bar-offset, 80px));
}
I utilized these root class names to be used in index.js on the component parent div
<div className="w-full
sticky
top-[var(--navigation-bar-offset,80px)]
h-[var(--gp-placement-max-height,auto)]">
<MapBox searchResults={searchResults} />
</div>
I also found, that Mapbox was overriding my height from it's setViewport callback in Map.js. So I overrode Mapbox by adding this code in Map.js in the onViewportChange.
onViewportChange={nextViewport => setViewPort({ ...nextViewport, width: "100%", height: "100%" })}
I updated the Codesandbox to reflect these changes.
Also, if you resize the browser, it maintains height and width.

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.

make flex-item honour width only if there is content

I want create a flex-item which takes a width of 33% of the container only if there is some content present as follows:
<FlexItem width='33%'> <Somedom /> </FlexItem>
Here, the FlexItem is a component that can take all flex properties as props and renders a div. Now, Somedom can render null in the dom in which case I want the FlexItem to take no width at all and allow the sibling div to fill the entire container.
I was wondering if there is any flex based arrangement which can help me achieve that. Further I have no good way of knowing if its going to render content or not. I don't want to move FlexItem component in Somedom as well.
Using #04FS suggestion of :empty
You could do something as simple as this.
.FlxRw {
display: flex;
}
.Flx {
flex:0 0 33%;
background:#cdf;
}
.Flx:empty {
flex:0 0 0%;
}
<div class="FlxRw">
<div class="Flx"></div>
</div>
<div class="FlxRw">
<div class="Flx">Content</div>
</div>
<div class="FlxRw">
<div class="Flx"></div>
</div>

Style a property in ReactJS

I got React noob question.. The thing is that I have a method with a mount of JSX attributies with their respective properties.
The question is, how can I get to the imageUrl attribute a style? such as give border-radius: 10px or centering in the page.
xxxx (item:aaaa, index:bbb) {
return (
<div className="Post ms-u sm3 ms-u-lg3 ms-u-xl">
<div className="content">
<PersonaControl
id={"BlogItem" + index}
identifier={item.blogOwnerEMail}
displayName={item.blogOwnerName}
size={PersonaSize.extraLarge}
hidePersonaDetails={true}
imageUrl={item.blogLeaderPicture && item.blogLeaderPicture}
labels={this.props.labels}
/>
Here is the render method. I try to double the information of the property xxxx how calls me the content of the parameter aaaa:
render() {
return (
<div className="clearBoth"></div>
<div className="bandContent" style={{ backgroundColor: this.props.backgroundColor }}>
{this.state.leadershipBlogDataItems.map(i => {return this.leadershipBlogDataItems(i, this.state.leadershipBlogDataItems.indexOf(i))})}
<div className="blogPost"></div>
You simply have to add a style property. You can do this by adding:
<div style={{ border: "1px" }} > </div>
If you want to add the "classic" css, with a file, simply add a className to the div, and import the css file as shown below.
import "./style.css";
<div className="yourstylename"> </div>
Inside style.css you simply add your css. By the way, the import shown above only works if the css file is in the same folder as your component/js file.

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