Delete a Container with an Anchor - javascript

I'm new to React and I'm creating a Wiki of my repositories on GitHub.
So, I want to remove that item from my list when I click "Remover" and open the repository on a new page when I click "Ver repositório".
But there's is my problem!
When I click the red anchor, it does remove, like I expected. Also, when I click the blue Anchor, it open the repository page and ALSO removes the list. What should I do?
This is the function that I created to remove the repository:
const handleRemoveRepo = (id) => {
const remove = repos.filter((repo) => repo.id !== repo.id);
setRepos(remove);
if ((repo) => repo.id === repo.id) {
return null;
}
And this is the container to map everything:
<Container>
{repos.map(repo => <ItemRepo handleRemoveRepo={handleRemoveRepo} repo={repo} />)}
</Container>
My container comes from this index.js:
<ItemContainer onClick={handleRemove}>
<h3>{repo.name}</h3>
<p>{repo.full_name}</p>
Ver repositório <br />
Remover
<hr />
</ItemContainer>
Thanks in advance.
React App page for example
I tried switching the conditional on my function, exporting a new function on ItemRepo, but both didn't work.

The "remove" click handler is assigned to the container, so it will be invoked if you click anywhere in the container:
<ItemContainer onClick={handleRemove}>
If it should only be invoked when clicking a specific link, assign the click hander to that specific link instead:
<a href="#" className="remove" onClick={handleRemove}>Remover</a>
As an aside... This shouldn't be a link. It's not navigating the user anywhere, but is just performing an action in code. A <button> is a more semantically appropriate element for that. Which can be styled to not have the defaul button background, or styled however you want.

Related

Render a whole new componnent on callback event (onClick for example)

I am trying to render a whole new component into a page when there's is event.
For example I have a button that sends request to DB, and I want that whenever this button is clicked a NEW toaster will open that will say "sent".
I saw this - Way to render a new component onClick in react js
And it just shows how to set toggle to show or hide element, but I want to add new one, so I will be able to add multiple of them.
export default function Demo() {
function handleClick() {
// show notification "clicked"
}
return (
<div>
<button onClick={() => handleClick()}>Click to update</button>
</div>
)
}
You can find a working sample in this codesandbox. I have used ant design to generate the notification. This comes out of the box without custom config. You can click the button as many times as you want and each time a new notification will be displayed.
The only things you need to do is:
Add antd to your dependencies in package.json
Add import "antd/dist/antd.css" to your index file
Start using notification right away in your component.

How to execute function when anchor tag was opened?

I want to send a post request (with a payload) to my server when a user opens a link in my React app.
My current approach is to use the onClick and onAuxClick callbacks, and then filter out right-clicks (because those don't directly open links).
<a href={link} target="_blank" rel="noopener noreferrer"
onClick={onLinkClicked} onAuxClick={onLinkClicked}>
<FaExternalLinkAlt className={styles.headerButton} />
</a>
function onLinkClicked(event: MouseEvent) {
if ([0,1].includes(event.button)) {
alert('track click')
}
}
However, right clicks followed by opening the link via the context menu are also ignored.
Another option seems to be to use the ping callback. However, there are two problems with this: Ping doesn't seem to contain a payload/body, which I need. And browser support seems to be flaky.
How can I reliably track link clicks without false positives and without ignoring opening the link via the context menu (and any other ways of opening a link)?
You can force the link to be opened even if the user clicks the wrong button and with that you ensure the actual click count
Edit 1:
For some reason, the contextmenu event fires twice so I advise that you handle that issue I tried removing the event propagation and investigating on it and found nothing
const a = document.querySelector('a');
// left, right, middle Clicks
const events = ['click', 'contextmenu', 'auxclick'] // You can add more events if you feel the need to
const cb = (clickType, elem) => {
console.log(clickType);
console.log(elem.href);
// Open link and do the post request here
}
events.forEach(eve => {
a.addEventListener(eve, (e) => {
e.preventDefault();
cb(e.which, a);
})
})
click

How to use div like link to redirect to another page?

I need to make div which will act simulate to Link element, so when you click on it you navigate to another page.
Something like this
<Link to="/employees">
...
</Link>
But it has to be div.
I could use onClick but when I use it, I should use whole path https://pro.websire.com/employees. I don't want to use it because we have different versions of website.
So path should be exactly like in Link element
<div onClick={to('/employees')}>
...
</div>
Does anyone know is it possible to do ?
If you are using react router, you can programmatically navigate using the useNavigate hook. Inside your component, you need to do the following.
const LinkComponent = () =>{
const navigate = useNavigate()
return(<div onClick={() => navigate("/home")}>Link </div>)
}

Input click can't be triggered programanticly on iOS <12

I'm having an issue with triggering the opening of a file dialogue on older iOS devices, specifically, the issue seems to be on devices that still run iOS 12.
I'm using the React-Dropzone package to create a dropzone for files, but also adding a way to tab the area to open the file dialogue to select files.
I then use Hammerjs to detect onTab events.
What I can establish, by adding an alert to be fired when onTab is called, is that the onTab event is firing and that it is the functions that are meant to open the dialogue that is not triggering the file dialogue to open on older iOS devices.
const FileUploadDropzone = () => {
...
const {getRootProps, getInputProps, open, inputRef} = useDropzone({
// Disable click and keydown behavior
noClick: true,
noKeyboard: true,
});
const handleTap = useCallback(() => {
// specific function created by React-Dropzone to open the dialog
open();
// also tried to trigger the input click directly using a ref (have confirmted that the input is correctly referenced)
inputRef.current.click();
}, [allowInteract, uploading, open]);
return (
<Hammer onTap={handleTap}>
<div {...getRootProps()}>
<input {...getInputProps()}/>
{children}
</div>
</Hammer>
);
};
From what I have read, the input cannot have styles set to display:none, if it does then you cannot programmatically trigger opening the file dialogue.
So I have set the styles as following:
input {
visibility: hidden;
height: 0px;
width: 0px;
}
What I've also tried to do is to wrap the input and the child element passed to the component in a label, hoping that clicking on a label to open the dialogue will be better supported, but even that is not working.
So now I am at a loss, I don't understand how to get this to work on these older iOS < 12 devices.
The issue seems to be related to an issue with fact that Safari on iOS 12 does not like it when there is any delay between the custom click event and until the input click event is called programmatically. Since the input in my case is deeply nested into the DOM, it causes an issue when the bubbling of the event takes to long.
To get around this issue, I had to create a hack, to append the file input into the DOM to make it as shallow of a grandchild as I could of the <body>.
I followed this article to utilise React.createPortal to append the input outside of the component. https://www.jayfreestone.com/writing/react-portals-with-hooks
I created a function to create an empty div at the bottom of the top <div> off the React application.
function usePortal(cssSelector) {
const rootElemRef = React.useRef(document.createElement('div'));
useEffect(
function setupElement() {
const {current} = rootElemRef;
const parentElem = document.querySelector(cssSelector);
parentElem?.appendChild(current);
return function removeElement() {
current.remove();
};
},
[id]
);
return rootElemRef.current;
}
Then created a component that would append its child a custom div, created by the function above
const Modal = ({children}) => {
const target = usePortal('#react-root-div');
return ReactDOM.createPortal(children, target);
};
And then simply wrap the input element with the Modal component and it will be appended (almost) to the bottom of the DOM tree.
<Modal>
<input {...getInputProps()} />
</Modal>

react-router-dom Link - hide URL on hover

I'm using MemoryRouter and I don't want the browser to show the full link (in the bottom left corner) when hovering over Link.
<Link to="/somepath" />
Using a function in the to property didn't seem to work.
I know it wraps an <a> tag inside but it still uses href even when passed a function in to.
Any way to implement this?
If you don't want to show the link onHover, consider making the page change programatically with onClick instead of using a Link, as they appear as a normal a tag with it's own href attribute, exposing the URL.
Here's a snippet from the docs
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}

Categories