How can I get current displayed div id in react? - reactjs

when the user scrolls the screen, I need to know the currently displayed div id to set the div key selected.
<button
type="button"
//here, I want to access current displayed div id
// I need to add some css class based on current displayed div id
className={`header_link ${
current_displayed_div_id === "Video" ? "selected" : "" // here I need to check
}`}
onClick={() => {
scrollTo(videoRef.current);
}}
>
Price
</button>
//here is my div using creatRef
<div
className="section"
height:
id="Video"
ref={videoRef} style={{ "auto" }}
>
<div>
<div className="nav-item">
<span className="nav-link">
<i className="icofont icofont-contacts"></i>
{translate("video")}
</span>
<div className="material-border"></div>
</div>
</div>
<div className="mt-4 text-center">
<div className="embed-responsive embed-responsive-16by9">
<iframe
src={this.props.datatab.video}
title="video"
>
</iframe>
</div>
</div>
</div>
when user scrolls the screen, I need to know the currently displayed div id to set the div key selected.

You could use the browser's native Intersection Observer API to track if an element is on screen and integrate this into your React component setup. Or you could use a React library like https://github.com/researchgate/react-intersection-observer or https://github.com/fkhadra/react-on-screen which should work out of the box.

Related

React Responsive Carousel returns all items in array on single carousel page

I am trying to utilize React Responsive Carousel. Currently, with my implementation, this code returns all objects in the array on the 1st page of the carousel (rending the point of a carousel useless). I'd like to have it so that each page of the carousel only shows one object in the array and you would need to utilize the "next" or "arrow" button via the carousel to view the next object in the array.
I tried to change profiles.map to profiles.forEach though this doesn't return any object at all.
I'm currently in a coding bootcamp, so forgive me if the code is bad altogether.
const { loading, data } = useQuery(QUERY_PROFILES);
const profiles = data?.profiles || [];
return (
<Carousel>
<div className="flex-row justify-space-between my-4">
{profiles &&
profiles.map((profile) => (
<div className="card col-12 col-xl-6" key={profile._id}>
<div className="card-body">
<h3 className="card-title">
{profile.firstName} {profile.lastName} <br />
<span className="mechLoc">
Location: {profile.location}
</span>
</h3>
<Link
className="seeProfileBtn btn btn-primary"
to={`/profiles/${profile._id}`}
>
See mechanic profile
</Link>
</div>
</div>
))}
</div>
</Carousel>
);
}

Tooltip for each option of dropdown

I want to show the tooltip for each option of using react-tooltip, I have tried below code which is working fine to show tooltip on mouseover, but on keydown and keyup arrow it not works because the focus never come to inner child div, which I have created as below...
Here, I updating options with tooltip div
updatedOptions = updatedOptions.map((option) => {
return {
value: option.value,
label: (
<>
<ReactTooltip
role="tooltip"
className="cb-select-tooltip"
type="info"
place="right"
effect="solid"
id={option?.value}
/>
<div
data-for={option?.value}
data-tip={option?.tooltipContent}
data-event="mouseover focus"
data-event-off="mouseout blur"
aria-label="option"
className="select-option"
ref={this.selectOption}
role="button"
tabIndex="0"
>
{option?.label}
</div>
</>
),
};
});
There is always a parent div creted,
`
<div role="listbox" id="react-select-2-menulist">
<div class="select__option css-3dmylm-option" id="react-select-2-option-0" tabindex="-1">
<div class="__react_component_tooltip place-right type-dark " id="" role="tooltip" data-id="tooltip"></div>
<div
data-for=""
data-event="mouseover focus keydown"
data-event-off="mouseout blur keyup"
aria-label="option"
role="button"
tabindex="0"
class="select-option"
></div>
</div>
<div class=select__option css-3dmylm-option" id="react-select-2-option-1" tabindex="-1">
<div
class="__react_component_tooltip place-right type-info select-tooltip"
id="<"
role="tooltip"
data-id="tooltip"
style="left: 270px; top: 174px;"
>
Less than
</div>
<div
data-for="<"
data-tip="Less than"
data-event="mouseover focus keydown"
data-event-off="mouseout blur keyup"
aria-label="option"
role="button"
tabindex="0"
class="select-option"
>
<
</div>
</div>
`
my question is, can we have control on that outer div HTML, while modifying option.
Or please suggest if I'm following wrong approach.

React Hook not opening form onClick

I am trying to refactor from class based to functional. While doing so I will need to use hooks instead of setting this.state etc.. I am trying to get a FORM to open when i click a button. The button will also change from "add reply" to "submit comment" once the form opens. I am stumped. This is the best thing I could come up with... Doesnt work. in fact, it makes my "add reply" button completely disappear. Any thoughts on this? Here is the code that I have written. inside of the comment I am trying to return a component using ternary....
image of component as-is
import React, {useState} from 'react';
import FormOpen from './FormOpen';
const CommentCreated = (props) => {
const [resource, setResource] = useState([{visible: false, addReply: 'Add Reply'}]);
return (
<div className="ui threaded comments">
<h3 className="ui dividing header">Comments</h3>
<div className="comment">
<a href="/" className="avatar">
<img alt="avatar" src= {props.avatar} />
</a>
<div className="content">
<a href="/" className="author">{props.author}
</a>
<div className="metadata">
<span className="date">Today at 5:42PM</span>
</div>
<div className="text">{props.content}
</div>
<div className="actions">
{resource.visible ? <FormOpen /> : null}
<a className="reply" onClick={() => {setResource([{visible: true, addReply: 'Submit Comment'}]);}}>{resource.addReply}
</a>
<a className="save">Save</a>
<a className="hide">Hide</a>
</div>
</div>
</div>
</div>
);
};
export default CommentCreated;
You should replace the setResource(['Submit Comment', true]) with :
setResource([{
visible: true,
addReply: 'Submit Comment'
}])
To match the shape of your state.
EDIT:
Here is a working example based on your code.
As I can see from your example, your resource state doesn't need to be an array but simply an object.
Furthermore, as you are using hyperlinks <a />, you must use preventDefault() on your event being triggered if you don't want the page to refresh.

React panel is squashed in tab that is not directly loaded - React Equalizer

I am using React, Redux and Bootstrap setup. I am building book website that have different tabs in that tabs are items(books) that have the same id through the different tabs. All my data is stored in a store and passed down to panel like so: TabsContainer(here I filter the books and pass down via props)->[All, Favorites, ...]->List of Books (all the same for every one) -> Book (all the same).
It is hard to post all the code and also basic concepts since I don't have idea what could be wrong. I instead post the result.
This is where it is ok. I can also fix the bug by resizing the window, but then it bugges the other 4 tabs.
This is clearly a bug. Bugg happens always when I move aways from inital tab.
What could be wrong? Should I set different keys? But if I understand correctly the react would do necessary rendering.
Update Found the root of the evil is the react Equalizer that I used to match column sizes (bootstrap responsive) so that button row appeared on the bot. I believe that has to do with incompatibility with React. So the problem now is how to put button row on the bottom of the panel.
<div className="col-md-12 col-lg-6">
<div className="panel panel-default no-padding">
<div className="panel-body contentRow" style={book_item.mainContainer}>
<Equalizer>
<div className="col-xs-12 col-sm-6" style={book_item.imageContainer}>
<div>
<FavoriteIcon reading={reading} style={book_item.favorites}
onFavoriteChanged={this.onFavoriteChanged}/>
<Link to={"readings/"+reading.id+"/edit"} params={{id: reading.id}} style={book_item.imageLink}>
<img
src={'http://smartbooky.hopto.org/media/images/books/' + reading.book.id + '.jpg'}
height="210px" style={book_item.bookImage}/>
</Link>
</div>
</div>
<div className="col-xs-12 col-sm-6" style={book_item.textContainer}>
<div className="bookTitle">
<strong>{reading.book.title}</strong><br/>
</div>
<div className="bookSubtitle">
{(() => {
if (reading.book.subtitle)
return (<div><em>{reading.book.subtitle}</em> <br/></div>);
})()}
</div>
<div className="bookAuthors">
<div>{authors ? authors : "Unknown author"}<br/></div>
</div>
<div className="bookDescription hidden-xs" style={book_item.bookDescription}>
{truncatedDescription.replace(/<\/?[^>]+(>|$)/g, "")}
</div>
<div className="bookTags hidden-xs row" style={book_item.bookTags}>
{reading.book.genre ? BookCard.renderTags(reading.book.genre) : void(0)}
</div>
<div className="buttonRow"
style={window.innerHeight > 400 ? book_item.buttonRow : void(0)}>
<div className="col-xs-4">
<Button icon="glyphicon glyphicon-remove" name="Remove" kind="primary"
handleClick={this.onReadingDelete} style={book_item.buttonRemove} />
</div>
<div className="col-xs-4">
<Button icon="glyphicon glyphicon-th-list" name="Shelf" kind="primary"/>
</div>
<div className="col-xs-4">
<Button icon="glyphicon glyphicon-edit" name="Edit" kind="primary"/>
</div>
</div>
</div>
</Equalizer>
</div>
</div>
</div>
Creator of react-equalizer here. It is possibly an issue with the equalization happening before the image is loaded. I just published a new verion that fixes this issue (1.0.5).
Here is a working example with react-bootstrap tabs:
http://jsbin.com/mayanakiqo/edit?js,output
class MyComponent extends React.Component {
render() {
let colStyles = {
float: 'left',
width: '50%',
padding: '10px',
background: '#ddd',
border: '4px solid white',
boxSizing: 'border-box'
}
return (
<div>
<Tabs defaultActiveKey={2}>
<Tab eventKey={1} title="Tab 1">
<Equalizer byRow={false}>
<div style={colStyles}>
<img src="http://placehold.it/200x300" />
</div>
<div style={colStyles}>
Test content
</div>
</Equalizer>
</Tab>
<Tab eventKey={2} title="Tab 2">
<Equalizer byRow={false}>
<div style={colStyles}>
<img src="http://placehold.it/200x300" />
</div>
<div style={colStyles}>
Test content
</div>
</Equalizer>
</Tab>
<Tab eventKey={3} title="Tab 3">
<Equalizer byRow={false}>
<div style={colStyles}>
<img src="http://placehold.it/200x300" />
</div>
<div style={colStyles}>
Test content
</div>
</Equalizer>
</Tab>
</Tabs>
</div>
)
}
}
The other option would be to use flexbox to equalize the heights see https://codepen.io/imohkay/pen/gpard for example however it will depend on what browsers you need to support.
I think before answering this there are some things we need to know:
1. Do these Bootstrap tabs implement some sort of non-React JavaScript in terms of switching between them? I know that Bootstrap not only provides CSS files for installation, but it also can provide some JavaScript too to use some of its components.
2. I am guessing that in the pictures you posted, you are navigating from the Favorites Tab, to the All tab? If so, what SHOULD the All tab show? (It is possible that it is actually rendering the intended elements, and it is just the css that is making it look wrong.)
3. If the top two points are not the source of the problem, then we will need to see some code, at least for the render functions of the components involved, as well as what their states look like.

How can I use angular ng-repeat to generate rows of 4?

I have a simple ng-repeat generating image divs. I want them to come out in rows of 4 instead of one long vertical list. How can I do this?
<div ng-repeat="artist in artists">
<div>
<h3> {({ artist.fields.title })} </h3>
<img src="{({ artist.fields.link })}" />
</div>
</div>
I believe you want to do something like this
<div style="width:800px;">
<div ng-repeat="artist in artists" style="width:200px;float:left;">
<div>
<h3> {({ artist.fields.title })} </h3>
<img src="{({ artist.fields.link })}" />
</div>
</div>
</div>
By having a container with a fixed width, and having each element inside be 1/4 of that width you can achieve what you want.
Of course, inline styles shouldn't be used in real code :)
You can use the $index property to add a tag every 4th item. Then use some CSS to display items as desired:
<div ng-repeat="artist in artists">
<div class="someClass">
<h3> {({ artist.fields.title })} </h3>
<img src="{({ artist.fields.link })}" />
</div>
<br ng-if="artist.$index % 4 == 0" />
</div>
One way is to use css properties. attach a class to the div with a float:left attribute, and insert a br tag after every 4th div
I guess you are using bootstrap?
If yes, this thread could do a help:
Bootstrap's grid columns number per row
doc for bootstrap grid layout:
http://getbootstrap.com/css/#grid-example-mixed

Resources