I have a window variable accessible in my webview like window.x Android/iOS is changing the value of x based on certain conditions, problem is this value changes but react is not able to rerender based on said change since its not a state.
Is there any way to fire a callback when this value changes without polling it continuously?
Found a better way to communicate events to a webview running on Android/iOS, requires minor changes to native code.
How to trigger webview events from native code
Related
I was working on a component that has a button which toggles a boolean. This boolean is supposed to determine if a child component in the HTML need to re-render or not, since I want the ngOnInit function in the child to be re-run.
The situation is described in the app component here: https://codesandbox.io/s/angular-qxtm8
The app.component is the parent and second.component is the child.
I have tried three different solutions. They are onTestClickOne, onTestClickTwo, and onTestClickThree in app.component.ts. onTestClickOne and onTestClickTwo successfully re-triggers the ngOnInit in the child component. We can see the console log in it is printed on the console whenever I click the corresponding buttons. However, onTestClickThree didn't work.
I'm not 100% sure why onTestClickThree didn't work, and onTestClickTwo did.
My guesses are the following:
onTestClickTwo works because the change detection in Angular is run after the event handler has been executed. So, it will detect the boolean has been set to true. After that, the event loop will get the callback of the setTimeout and put it into the stack. Angular will execute change detection after finishing the callback.
onTestClickThree didn't work because, by the time Angular runs change detection, the boolean is already true. Angular doesn't know that it has been changed.
Let's tackle the main issue there, which is your design : why would you re-render the component to trigger ngOnInit again ?
Sure, in the case of your example, that's no big deal. But what happens for a fully coded component, making http calls, having children and all ? That will cause some severe performance issues.
Instead of re-rendering the component, you should use a function to do that.
If the event (that is initially supposed to re-render the component) comes from the child, then use an #Output. If it comes from the parent, use a #ViewChild reference.
As you can see it works well, without any detection issue.
I'm working on an App which displays some information to the user. This information changes multiple times per day (sometimes multiple times per hour).
I'm using Firebase and setting listeners for this information.
Is it reliable to assume that these listeners will always work?
If the app is not closed (so the component is never unmounted), will the listeners ever expire/close?
Is implementing a pull-to-refresh a more reliable way to update information.
The situation I'm worried about is something happening with a listener and the only way the user can then update the app is by shutting it down and restarting to trigger new listeners.
once the app is closed the listner wont work
no it ll keep listnening if the system have enough battery or the app is not closed by the system. [when app remains in background the app is disbaled by android system to save battery and when the user comes it restarts]
it depends upon the kind of application is. if the app is some stocks or chat kind of thing then data must stream in real time while if the app displays some posts by some other user like in twitter user profile then pull to refresh is ok
RECOMMEND: you should also make a retrial function to check the state of the listener if it goes of then retry [helpful where there is a network break] moreover you should also give a mechanism to the user to refresh as it imprves the UX ;)
You have to understand the react component lifecycle before getting an answer to this, listener will always be a part of some component and listener will be initialized when some component is initialized into the memory and listener life is dependent on that component once that component is unmounted from the memory that specific listener will not be invoked so now the answer of your first question is.
Even the app is not closed and you are navigating between the different screens and you put your listener in some child component and that component is unmounted from the memory your listener will not work.
Now came to the second question which is almost answered in my first answer.
So as I said in the first answer Until that component unmounted from the memory, the listener will work unless you close the app or the operating system kills the app due to some reason but as long as the component keeps mounted into the memory your listener will keep working.
I believe adding a pull to refresh is more convenient in your case another option is that you can use a mixture of your change listener and focus listener of your navigation library, When the user focuses on some screen then you can fetch newer data and in that way always fresh data will be displayed instead of manual refresh.
So, I have run across an issue where due to maintaining a state for an input field; breaks the user experience of the app when they use an extension like Grammarly in their browser. Problem as I figure is since the state is immutable and Grammarly changes the DOM without triggering an change. So in that the state doesn't change, and thus the changes from Grammarly are lost, it let's say that input is part of a form, and I hit submit. The data from reacts state gets sent down, not the visual changes grammarly made.
So my overall question is.. does anyone know of a method, means, or practice I can deploy to capture instances like this and work with them properly.
You can try to use MutationObserver for detection of external changes of the DOM nodes, and then apply them to the state like a regular input.
Re: For more information about Grammarly extension compatibility, you can check this thread.
And also, Grammarly will release developers guide in the near future.
I'm writing a Chrome extension for Facebook and want to programmatically trigger the submission of the focused comment draft on a post. The default behavior is to submit when the user hits the Enter key, so I'm attempting to trick the Facebook UI into thinking that the user did so.
Facebook uses React and a contenteditable div for comment forms.
Here's a set of things that I've tried:
1) jQuery Event triggering $('<the contenteditable div>').trigger($.Event('keydown', {which: 13}))
I've tried this from both the content-script environment and the actual page environment (via both an injected script that responds to postMessage and the Chrome console)
I've also tried triggering the event on the document, from each context.
Nothing seems to happen.
2) Same thing, but with VanillaJS event triggering. relevant StackOverflow question
also from both environments
Nothing happens
3) At this point I realized that this is React and it uses it's own SyntheticEvents, so I basically copy/pasted the Simulate function from ReactTestUtils that's supposed to help testing by simulating events and ran that within the page's environment (grabbing references to the required objects via Facebook's frontend require function).
Also does not work. The function executes fully and without errors, but there's no response from the application.
I've tried this with mostly keydown events, because that has the most listeners attached to it.
I'm aware of these questions, but they haven't helped my understanding: Force React to fire event through injected JavaScript
It's unclear based on your description whether or not this is an issue, but SyntheticEvent has caused me pain before due to the fact that the object is reused. There's a note in the React docs about this:
If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.
If you aren't immediately using the event, or if you are trying to pass it into a new scope, you'll need to persist() it.
After digging into the code a bit I see that invalidate() on a control will increase a counter which seems to mark the control as invalidated.
This seems to lead to a rerender.
So if you have a control that you want rerendered, is it better practice to use invalidate() or rerender()?
How does a rerender actually get triggered? (other than by explicitly invoking it of course)
Both are marked as "protected", meaning you should not call any of them unless you are really deep into developing custom controls.
A control gets invalidated when (for example) a property is changed. In that case you usually want to re-render the control, that's why setters call invalidate by default.
When you overwrite your invalidate method in your custom control, you can analyze the source of the invalidation and then decide whether you really want to rerender etc. See for example the unified.Shell which decides what to do on invalidate based on the source:
https://sapui5.netweaver.ondemand.com/sdk/resources/sap/ui/unified/Shell-dbg.js line 1539ff
Again: Protected means that it should not be called from the outside (and that it should not be necessary, except for debugging).
Is it better practice to use invalidate() or rerender()?
As an application developer
Neither invalidate() nor rerender() should be used as they're not public APIs.
As a control developer
Usually, the framework already manages rerendering of the controls automatically if one of the control settings (properties, aggregations, or associations) changes. But if it's still required to trigger the rerendering explicitly, the API invalidate() should be favored over rerender() because:
rerender()
renders the control synchronously (blocking the main/UI thread)
works only when the control has been rendered before (no initial rendering possible)
does not combine multiple state changes into a single rerendering
causes additional layout trashing
has become deprecated since 1.70.
invalidate(), on the other hand, just adds the control to a collection of to-be-rendered controls so that it can be rendered together with them in one process asynchronously (currently in the next browser task using setTimeout(fn, 0)).
I encountered such thing in my work recently. I am fixing an animation issue but the bad thing is I have to start the animation after rendering. If that is all I can handle it, but the worse thing is the control rendering twice. When the first rendering happen, the animation start to do, but the second rendering comes immediately and the DOM was restructed, then the animation is terminated and the effect is like no animation executed. After investigate the code, I found there is a place invoke render() method which will execute render immediately. After change it to invoke invalidated() method, it looks the animation works well. It looks multiple invalidate() method invocation only cause executing render once.