React keep track of element clicked - javascript

I have a list of items like this:
<div className="items-section">
{items.map((item) =>
<Item key={item.id} {...item} />
)}
</div>
When user clicks on an item from the list, they will get redirected to /items/:itemId url to see that item, when they click to go back or close that modal that will display that item, I want to display the list and focus on the element where they stopped and clicked. How is it working now, 20 items are displayed to the user, they click on the 11th item, then click back and again list is displayed starting from the top page from 1st item. How can I make it to get back to that 11th element for a better experience?
I am using redux as well and I thought to keep track of the element clicked, but how to reflect this in React and display from that element. I thought of useRef but I do not see how to use here. Could anyone please suggest me what to do and how to achieve this?

You can give ids while you are mapping your list. Like this
{items.map(item => <div id={`foo-${item.id}`}>foo</div>
then whenever you want to select this item you can
const foundItem = document.getElementById(`foo-${here is your stored item.id in redux}`)
and now you have this node. If you want you can scroll to this node by using scrollTo or if you want give a class.

Related

How do I get the website to look the same after clicking a link and coming back?

I am filtering products by color/size on a page with a list of products, using <select onchange="myFunction()">.
The filtering works fine, but if a user clicks a product and is moved to the product page, then clicks the browser back button, the select box shows the right color/sizes but the list is not filtered. The user would have to select a different color/size and then the same color/size again to see the correct list (or I'd add a Filter button).
Is there any way to make sure the user gets the filtered list right away when using the back button?
Ideally, I would not like the myFunction() to run again, as that might cause the user to have to scroll down, but rather just have the site look the same way it did before clicking the link.
You can persist values across refreshes/naviagation by using localStorage, by doing something like this:
<select onchange="onSelectChange">
// when the user selects a value, save it
const onSelectChange = event => {
localStorage.selectValue = event.target.value;
}
// when the user navigates to the page, if there is a saved value, set it
if (localStorage.selectValue) {
document.querySelector('select').value = localStorage.selectValue;
}

Can't select item from custom autocomplete search bar (Vue.js/Vuetify.js)

NOTE: I'm not using v-autocomplete or v-combobox because they aren't able to do certain things that I want.
I'm having trouble implementing an autcomplete search bar. The search bar does everything as expected except for one minor thing, and that is being able to select an item. When I hover over an item, the pointer changes to a hand indicating that it's clickable. Once "clicked", a #click event is supposed to call a method, but nothing happens when an item is "clicked".
I know what the problem is, but I'm struggling to find a solution for it. The problem stems from these parts:
<v-text-field //this is the input
...
#focus="isFocused = true" #blur="isFocused = false"
...
></v-text-field>
<v-list v-show="queried_cards.length && isFocused"> //this is the list
<v-list-item #click="setCard(card)" v-for="(card, index) in queried_cards" :item="card" :key="index">
...
</v-list-item>
</v-list>
So, based on the above markup, I only want to show the list if the array queried_cards is not empty and if v-text-field is focused on. If I click out of the textfield then the list is hidden, which is the desired outcome that I want. It just so happens that it conflicts with the functionality of being able to select an item since when you click on an item, that is the same as clicking out of the textfield (triggers #blur). This results in the method setCard() not being called since v-list disappears before the event #click="setCard(card)" can happen.
I've been putting this on backlog for awhile thinking I'll eventually be able to find a solution, but I'm just burnt out from all the other stuff from this project.
I created a codepen that illustrate my problem: https://codepen.io/chataolauj/pen/RwwYxBg?editors=1010
the issue is you set the list <v-list v-if="queried_cards.length && isFocused" class="pa-0 overflow-y-auto" max-height="300" two-line>
when you clicking on the list item, the isFocused set to false because you bonded #blur="isFocused=false" on the input filed. so it disappeared. you need to figure out a way to keep the isFocused to true when you select the items.
quicky way:
on your v-container bind a click function (you want to when user click outside of the input or the result list, hide the result lit):
<v-container fluid #click="checkHide">
checkHide(e){
// if click on input or the result list, keep the list to show
if(e.target.tagName ==="INPUT" || e.target.classList.contains("v-list-item__content")){
this.isFocused = true
}else{
// click outside of them, hide it
this.isFocused = false
}
}
on your input element, remove #blur.

React Conditional Rendering on click

I have a list of poem titles and images within article HTML tags. Whenever a user clicks on an article, I want a modal to show the poem verses. As of now whenever an article is clicked, the modals for every poem opens. How do I open the modals one at a time? This is my first time using React.
Link to my codesandbox:
https://codesandbox.io/s/and-air-52dpo?fontsize=14
You need to separate each Poem card to a component, and put the state inside them.
By using state on parent component as you did, it cause all poem card depend on same state.
I've forked your codesandbox, and fixed them. You can check it.
https://codesandbox.io/embed/and-air-543tl
You're using a single show variable in your Poems component.
This doesn't allow to show a single one of your modals, as all of them are referenced to this same variable.
I would use an integer in the Poems's state - rather than the boolean show - to store the currently presented modal.
The best option for this integer is probably the poem's index, as you should anyway add to your map function:
const listItems = data.map((poem, index) => (
<React.Fragment key={index}>
// The rest of your code is the same
<Modal
show={this.state.currentModal === index} // only this property was updated
onClose={this.showModal}
title={poem.title}
>
// modal code
</Modal>
</React.Fragment>
))

React.js: Get value from an icon component works inconsistently

A table component renders trash icons that I would like to bind to mapped couponId's to post delete requests through:
<FaTrashAlt
value={record.couponId}
onClick={e => {
console.log(e.target.getAttribute('value'), `=====e.target.getAttribute('value')=====`);
}}
/>
The first row of the table shows the couponId, seen below. Clicking the above does work maybe 10% of the time, but most of the time it returns null:
Clicking the same delete icon quickly lowers the chance of the value logging so I think there is some sort of async issue in play here.
What is a more reliable way to bind a value to an icon or image and pass it to an onClick handler?

Is there an elegant way with React-Router to clear the current component's rendered data, when one of its routes are matched?

I have a component called PastIssues, which lists all of the past editions of a magazine. The output of the component is an ordered list where each item is the year of release followed by the season. For example:
Spring:2014
Autumn:2015
Each of these items is a Link that points to a specific path. I've dynamically added to this component, such that my ShowArticleInfo component will be displayed. My issue lies, when the user clicks one of the Links, my ShowArticleInfo component gets rendered, but only below ordered list. I would like my ordered list to disappear, such that the only remaining component is ShowArticleInfo.
So before the user clicks anything, I want a list of links, one for each article (in the example above). After a user clicks one of them, I want the list to disappear and only ShowArticleInfo to appear.
Is there an elegant way to do this?
Use local storage to set a key with value true
componentDidMount(){
localStorage.setItem('loaded','true');
}
and clear local storage when u unmount component ShowArticleInfo.
In your ordered list component render.
render(){
let loaded = localStorage.getItem('loaded');
return(
<div style={{display:{loaded ==='true' ? 'none':'block'}}>
</div>
)
}
For further info on localstorage MDN/localstorage.

Categories