Consider this function (this is just an example):
function highlight(el) {
el.style.transition = "background-color 0.5s";
el.classList.add("highlight");
setTimeout(() => {
el.classList.remove("highlight");
setTimeout(() => {
el.style.transition = "";
}, 500);
}, 500);
}
document.getElementsByTagName("a").addEventListener("click", function () { highlight(this) });
This is "universal function" that automatically binds to every <a> on page onload, it is short (only several lines long) and I can add or remove it in seconds (the code on pages are intact).
What is the best approach to implement it in React App?
Course I knew the obvious way, with the manual add of onClick to every <a> in every component on page with setState logic, but ... it kinda sucks
I'm new to React, maybe someone can point me to the right direction
How I can implement this logic on every page(every component that has <a>) efficiently, with the ability to easy remove it if it is no longer needed?
Well, the way I see it, if you want the react way, then you would want to create a presentation component with the defined behavior and use that component instead of .
In fact, that would actually be a perfect fit for a presentational react component.
Then, if you need to implement any changes, you would do them inside that component.
You could alternatively add vanilla js to the index page but that kinda misses the whole point of react.
If you are currently developing this application then the best approach is to create a small tiny component for it. For example you can create a component HighligtedAnchor and can implement the stylistic features in it directly.
Secondly, if you directly want to handle a lot of anchors then the most appropriate place would be the root of your application that is usually App.js or you can write it down in the index.html as well if you really want to move forward with the plane js approach.
If you are looking at for something like good old jquery live you can't do that in reactjs.
The best thing you can do is to create a custom component that wraps the <a> tag. And use your custom component everywhere you would use regular <a> tag.
Related
I am having the same error as this person:
Add onclick event to SVG element
But I am having it in Angular which makes it even harder to deal with.
I want single SVGPathElement to be clickable & access component properties and functions in this click handler. But this is giving me the error 'property undefined' or 'function doesn't exist'.
According to this answer:
Add onclick event to SVG element
It's because all of the JavaScript must be included inside of the SVG for it to run.
But I cannot even do what the mentioned answer Add onclick event to SVG element suggested, since I get an error probably because Angular cannot create the component when parsing the html.
I also looked at http://xn--dahlstrm-t4a.net/svg/html/from-svg-to-parent-html-script.html (mentioned in the comments of the above answer) but that gave me the same error as in the picture above.
Now the second requirement to the solution to my question:
I am planning on having many different svgs and interacting differently with them. So manually pasting some <script> into the svg won't be a scalable nor maintainable solution for me. So actually I would prefer not doing this over the html with <script> tags at all.
If anyone has a good solution to solve both of my inquries in angular I would be greatful.
Additional Info:
I am using the ionic framework but I don't think it matters in this case
One possible alternative solution:
One could use ReactJS instead of Angular.
SVGPathElement<->Component interaction works in ReactJS without doing anything manually. I have no idea why but there is no such errors maybe because the component is not a class but rather a function. This would be great to know why exactly! I don't want to use ReactJS since I am not familiar with it. But maybe it's my best option to just switch frameworks since SvgPathElement<->Component interaction is a key part of my mobile app (it's like the seterra mobile app (https://play.google.com/store/apps/details?id=com.seterra&hl=en&gl=US)).
I found the culprit:
Don't do this (Angular doesn't allow it for some reason):
ngOnInit() {
document.querySelectorAll('.area').forEach((element: Element) => {
element.addEventListener('click', this.clickHandler);
}
);
}
Instead you have to add the click handlers manually like this:
<svg id="svgroot">
<path ... (click)="clickHandler()">
If anyone knows how to make this work by adding click handlers programmatically then this would make the solution a lot more automated/scalable/maintainable.
Adding click handlers programmatically to the SvgPathElement works in ReactJS for some reason, probably due to some internal differences between how the frameworks generate components.
I am making something similar to sheet with cells where using drag and drop i can move events, that are components, around.
Since it is possible to add component from any file like this
import event from "event.vue"
let el = document.getElementById("div")
const newComponent = createApp(event)
newComponent.mount(el)
Im trying to remove it somehow aswell, but i had no luck to find solution.
i have tried to this
let element = document.getElementById("newComponent")
element.parentNode.removeChild(element)
It's kind of working, but i can't add new component to same div because there is dataset remaining 'data-v-app' and i guess its because old component was not removed. Is there a way to do this or maybe vue isn't capable?
v-if is still the "official" way of doing things here because it uses Vue's reactivity.
Modifying the DOM is not recommended since it's imperative, like jQuery: you need to tell the language how to do things, so you need to take care of finding the selector, ask it to do things on it, and loop that process in case of an event listener or alike.
VueJS is declarative, so the API is far less complex. You tell what variable is bind to what and when the variable mutate, it will react accordingly to the changes without you needing to tell step by step what to do.
When you project grows, an imperative approach like jQuery or your vanilla JS (document.getElementById) will not be efficient because you will need to describe everything that happens once you mutate a variable. If 12 things depend on a thing, you will need pretty much the double of lines of code for each of them.
While in Vue, you will make some conditions thanks to the API and it will make those changes by itself. The complexity is then greatly reduced. On top of having powerful directives + Vue devtools to help you.
Add to that the fact that if you mix both some Vue state + imperative coding, you will have the worst of 2 worlds. You will need to do funky things to kinda keep the reactivity + will still need to write declarative code.
Hence why, people are using Vue's API + template refs only when needed.
Stay away from imperative coding: jQuery, manually selecting DOM elements etc...you will have an easier time, less complexity and more performance by far.
Vue/React exist for a reason, mainly removing complexity. Use them to their full potential.
A little bit of background, so I am essentially trying to convert the following library in react ( lib-jitsi-meet) and I am currently trying to use the example code, which uses generic javascript. I did make a hook to run it, and the way it works is by essentially appending a video tag to the body whenever a participant joins the meet.
if (localTracks[i].getType() === 'video') {
$('body').append(`<video autoplay='1' id='localVideo${i}' />`);
localTracks[i].attach($(`#localVideo${i}`)[0]);
}
However, directly interfering with the DOM doesn't really feel right. is there any way I can modify the code so that it follows the proper React principles?
I'm looking to trigger a route to another page in React (using React Router) after an animation is triggered. Off the top of my head, I know I can trigger the animation and Route after a setTimeout is complete, but something tells me that is not a good way to do it. Am I wrong about that, or is there a better way to cause a delay in routing to another page?
An example of what I'm thinking:
target.style.animation = 'example';
setTimeout(() => {
//Route here
}, 2500);
Assuming you're on a recent version of React, you can use the useHistory hook from react-router to programmatically navigate by calling history.push("/my-next-route") in your setTimeout callback. Check out the official docs for an example.
If your animation is already working and all you need to do is add the actual navigation part, that should get you there. If you want to know the "right" way to do this, you'll need to post more code so we can see exactly what you're trying to accomplish. There are some libraries for handling animations in React, and some others that help combine that with routing, but I can't recommend that as a solution without more context.
I have to render a lot of divs into DOM. So, what I did is I render the first 5 elements into the DOM first after that I render every 10 divs with 300ms interval period.
The problem is when I change into display: block I need to change something in the component. So, I try to use didRender hook for that.
Code is below
didRender() {
if(this.element.offsetParent) {
this.set('myvar', true);
}
}
But it's not working perfectly. Anyone please suggest me which is the best way to do this.
_Thanks in Advance.
It's hard to guess your use case from the question but I assume that it's about rendering a very large list of items without causing performance issues. The ember ecosystem provides bulletproofen addons to do so. The most established ones I'm aware of are ember-collection and ember-large-list. I would recommend to use one of these if they suit your requirements. Reimplementing something similar will be a lot of work. Rendering new items on a timeout basis would not scale well as it doesn't take workload of browser into account.
For your concrete question: Ember does not provide a way to listen to CSS changes. You should execute custom logic at the same place as in which you are mutating the property which triggers the CSS change. If it has to be run after render, you need to deal with Ember's runloop.