How to scroll beyond the focused element in React - javascript

I am working on a React App, and using antd as the UI-library. What I intend to do is whenever a button named Open Modal is clicked, a Modal will open up, and when user clicks on the Ok button in the modal, an input field will be displayed and page should automatically be scrolled to the top. However, since the input field contains focus, the scroll happens only until the input field becomes visible. Is there any way to make the page scroll to top, ignoring focused elements using JS only. This is the minimal code to reproduce the example:
const App = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
const [isInputVisible, setIsInputVisible] = useState(false);
const showModal = () => {
setIsModalVisible(true);
};
const handleOk = () => {
setIsInputVisible(true);
window.scroll(0, 0);
};
const handleCancel = () => {
setIsInputVisible(false);
setIsModalVisible(false);
};
return (
<>
<Button type="primary" onClick={showModal}>
Open Modal
</Button>
<Modal
title="Basic Modal"
visible={isModalVisible}
onOk={handleOk}
onCancel={handleCancel}
>
/*Some contents...*/
{isInputVisible && <input autoFocus />}
/*Some contents...*/
</Modal>
</>
);
};
This is the sandbox link to reproduce the use-case.
Code Sandbox

You can always use scrollIntoView method.
scrollIntoView
I tried with ref and useRef but it didnt work, so the other solution was to find the modal through it's class name and use the above method.
Check this
sandbox

I am not sure if it will work but I think you can work your way through with the useRef hook where you can focus after the click event. Refer this

Related

Open Modal in App.js from a button in another component

So I have three components in my app.
App.js
HeroSection.js
Modal.js
The button I have for opening the Modal is in HeroSection. But I need the Modal to render from App.js due to how the styling is structured. When it is opened from HeroSection, it opens in a container that doesn't allow me to position the Modal in the center of the screen (It's in a CSS grid set up). I hope I'm making sense.
My code:
const App = ({ signOut }) => {
return (
<div>
<button onClick={clickOpenAccountModal} className='add-account'>Add Account</button>
{openAddAccountModal && <Modal closeModal={setOpenAddAccountModal} />}
<div className="App">
<div className='nav-pane'>
<SideBar signOut={signOut} />
</div>
<div className='content-pane'>
<MainContent />
</div>
</div>
</div>
);
}
const HeroSection = () => {
// Add Acount Button
const [openAddAccountModal, setOpenAddAccountModal] = useState(false);
const clickOpenAccountModal = () => {
setOpenAddAccountModal(true);
}
// Add Transaction Button
const [openAddTransactionModal, setOpenAddTransactionModal] = useState(false);
const clickOpenTransactionModal = () => {
setOpenAddTransactionModal(true);
}
return (
<div className='hero-section'>
<h1 className='page-title'>Users's Dashboard</h1>
<div className='hero-buttons'>
<button onClick={clickOpenAccountModal} className='add-account'>Add Account</button>
{openAddAccountModal && <Modal closeModal={setOpenAddAccountModal} />}
<button onClick={clickOpenTransactionModal} className='add-transaction'>Add Transaction</button>
{openAddTransactionModal && <Modal closeModal={setOpenAddTransactionModal} />}
</div>
</div>
);
}
const Modal = ({ closeModal }) => {
return (
<div className='modal-background'>
<div className='modal-container'>
<div className='title-container'>
<h2>Add Account</h2>
<button className='exit-button' onClick={() => closeModal(false)}>X</button>
</div>
</div>
</div>
);
}
Main App
How the modal opens in HeroSection
How I need it to open from the button in HeroSection
I tried copying the logic for opening and closing the modal directly to App.js, but to get that to work, I had to put the button used to open the Modal in App.js as well. I need the button to stay in HeroSection and render from App.js
How can I accomplish this?
It is more valid to put the button in the HeroSection component and let the modal be opened in the App.js component. So to start it's the correct approach.
For the implementation there are 2 options:
1-
If the application won't grow to much more components, you can still have the open modal button in the HeroSection component. And that HeroSection component can take a callback function as a prop (for ex openModal) which it can calls when the button is clicked. That way when the function runs you implement the logic for opening/closing the modal in the App.js.
Check solution 1 in react codesandbox
2-
If the application can grow to many components, solution 1 will create unmaintainable code in the long run.
To address this, you can start using a general state management library like redux
When you do that, you can open/close a modal from any component you want without passing any modal specific prop to that component
In general applications, the more correct approach is solution 2. But it can be unnecessary complexity if the application only contains 3 component

How to close multiple dropdown in reactjs when click outside

I create custom dropdowns and handle through states in react.js
I used the below link code when I apply for two dropdowns then it's not working
When I apply on two dropdowns the 2nd dropdown value is changed and 1st dropdown value is not changeable
This is working on single dropdown but in multiple dropdown not working
How to close multiple dropdowns when clicking outside in reactjs
https://stackoverflow.com/questions/32553158/detect-click-outside-react-component
Without seeing your code, it is difficult to determine how to answer your question.
Your dropdowns are presumably controlled by state within the component.
Something like this?
const Dropdown = () => {
const [open, setOpen] = useState(false);
...
}
Then you have a parent component rendering the dropdowns.
const Parent = () => {
return (
<>
<Dropdown />
<Dropdown />
</>
)
}
Since the state is held within the components, we can't modify both at once. The solution is to lift state.
const Dropdown = ({ open }) => {
...
}
const Parent = () => {
const [openDropdowns, setOpenDropdowns] = useState({});
}

How to conditionally change visibility with React?

I am trying to change a div's visibility from hidden to visible using button click. But even when I am clicking the button, the visibility is not changing. I have logged the console after the clickHandler, and it still says false even after I set it to true inside the function. So far, I have this,
let clicked = false;
//change image on fortune cookie click
const clickHandler = (e) => {
e.target.setAttribute(
"src",
"https://i.ibb.co/cksx7kr/kisspng-fortune-cookie-drawing-clip-art-fortune-cookie-5b237469209879-9079770415290502171335.png"
);
clicked = true;
};
console.log(clicked);
return (
<div className="App">
<button onClick={clickHandler}>
<img
className="cookie"
src="https://i.ibb.co/9YQV2qq/kisspng-fortune-cookie-biscuits-bakery-drawing-clip-art-fortune-cookies-5b0ec5e3013c23-3980054715276.png"
/>
</button>
<div
className="fortuneMessage"
style={{ visibility: clicked ? "visible" : "hidden" }}
>
{fortune}
</div>
</div>
);
When you are using React, you need a state in order to have a DOM update. That would fork for you (don't forget to import useState at the top of your file) :
const [clicked, setClicked] = useState(false);
const [src, setSrc] = useState("https://i.ibb.co/9YQV2qq/kisspng-fortune-cookie-biscuits-bakery-drawing-clip-art-fortune-cookies-5b0ec5e3013c23-3980054715276.png");
//change image on fortune cookie click
const clickHandler = (e) => {
setSrc("https://i.ibb.co/cksx7kr/kisspng-fortune-cookie-drawing-clip-art-fortune-cookie-5b237469209879-9079770415290502171335.png");
setClicked(true);
};
console.log(clicked);
return (
<div className="App">
<button onClick={clickHandler}>
<img
className="cookie"
src={src}
/>
</button>
<div
className="fortuneMessage"
style={{ visibility: clicked ? "visible" : "hidden" }}
>
{fortune}
</div>
</div>
);
You'll need to use state instead of the plain clicked variable.
const [clicked, setClicked] = useState(false);
Call the setState function inside the clickHandler function instead of setting clicked to true.
setClicked(true);
in React, the variable is not two way binding.
The clicked variable in your function will only get to be true in the function itself but not outside the function
So in this case you need to use useState so that the clicked state will be re-rendered again with updated boolean
const [clicked, setClicked] = useState(false)
const clickHandler = () => {
setClicked(true)
}
so that your clicked variable will be updated, hence the css will be updated again.
for more reference with useState can check their documentation https://reactjs.org/docs/hooks-state.html

How to Double Click Toggle visibility of React Component?

Currently have a popup component showing up double click using the onDoubleClick() handler.But I'd like to close that popup on double click of the popup component but I can't seem to get it to work. Here is what I have been trying, the thought process was to just to set toggleModal to false and it should work.
const [selectedImageId, setSelectedImageId] = useState(-1);
const [toggleModal, setToggleModal] = useState(false);
const handleModalPopupOnClick = (id) => {
setSelectedImageId(id);
setToggleModal(true);
};
return (
<div>
{toggleModal && <PopupModal onDoubleClick={setToggleModal(false)}/>}
<div onDoubleClick{()=> handleModalPopupOnClick(image.id)>Open Popup</div>
</div>
)
Any ideas? Thank you for any suggestions or guidance.
The line
{toggleModal && <PopupModal onDoubleClick={setToggleModal(false)}/>}
Is immediately calling setToggleModal with an argument of false when the component is rendered, and I believe undefined becomes the value of onDoubleClick. (Not 100% on if setState has a return value or not)
To fix your problem you should provided this as a prop:
{toggleModal && <PopupModal onDoubleClick={() => setToggleModal(false)}/>}
This is providing a function definition rather than calling the function.
Maybe PopupModal is your custom component, so it doesn't provide onDoubleClick event.
onDoubleClick in this line:
{toggleModal && <PopupModal onDoubleClick={setToggleModal(false)}/>}
is just a prop.
So you must call props.onDoubleClick in the handler of onDoubleClick event inside the PopupModal.

Dismount and re-mount a component on each button click?

I want to conditionally render a custom notification component (not 100% sure how it works, it was written by others and it uses material-ui). I want this notification to appear every time a button gets clicked, but for some reason the notification component will stop re-appearing after it auto-hides itself after some time, even when I click the re-click the button - again, I'm not totally sure how this works.
I just want to know if there's a way to dismount and then re-mount this custom notification component so that it gets newly rendered on each button click (is that bad practice?). This is a simplified ver. of my current logic:
const RandComponent = ()=>{
const [notifType, setNotifType] = useState(1);
const toggleNotif = ()=>{
setNotifType(!notifType);
}
const getNotif = ()=>{
return <Notification type={notifType}/>
}
return (<>
....
<button onClick={toggleNotif}>TOGGLE</button>
{getNotif(notifType)}
</>)
}
You can do it like this
const RandComponent = () => {
const [showNotification,setShowNotification] = useState(true):
const toggleNotificationHandler = () => {
setShowNotification(p => !p);
}
return (<>
<button onClick={toggleNotificationHandler}>TOGGLE</button>
{showNotification && <Notification />}
</>)
}

Categories