I am working on creating a text highlighter with these functionalities:
It allows the users to select and highlight/unhighlight the text on
the page with different colors.
Load the highlights from a file (search for the words from the file in the page and highlight them).
I was able to create the highlight and delete highlight function using rangy https://github.com/timdown/rangy (which is not a react component), but whenever any component on the page sets the state using (setState method) those highlights disappear.
Also, previously highlighted items are not easily loaded into the page using this method.
That is why I am redeveloping this functionality again, and I want to know what would be the right approach to tackle this issue?
I have been thinking of developing a custom React component for highlighting and adding it to the page, but for this approach, I want to know how to dynamically add the highlights component when the user selects a text on the page without losing it when the state is updated.
A link to a useful resource on how to add dynamic components would be convenient for me as I have been searching for the correct way to tackle this issue for a while and I think I might not be heading in the right direction.
React will re-render anything where the state has changed. This will cause your highlighting to disappear as the elements are not the same even if they appear the same.
React will also intelligently not re-render if you set a unique key property in many cases. This lets React know to reuse the component.
If the state is correctly changing, and you only want to sometimes prevent a re-render, you should implement a shouldComponentUpdate lifecycle method to control the re-render conditions yourself.
Related
I'm doing a Chrome plugin for Facebook and I want to modify a post using external javascript. I can change the textContent of a span but the state is not changed and the Save button is not activated.
The html looks like that :
<div class="" data-block="true" data-editor="1477r" data-offset-key="a699d-0-0">
<div data-offset-key="a699d-0-0" class="_1mf _1mj">
<span data-offset-key="a699d-0-0">
<span data-text="true">test</span>
</span>
</div>
</div>
The component in React Developper Tools :
[
I profiled a change of the text and this is the result for a 6 ms timeline activating the save button.
There are ways to modify a React input but did not found ways for my problem :
https://github.com/facebook/react/issues/11488
https://github.com/facebook/react/issues/10135#issuecomment-314441175
How can you change a Facebook post and his state with external javascript?
What would you do?
That’s not possible, you can’t imperatively mutate a React element tree from outside the app. You’d have to declaratively render a tree, either by modifying Facebook’s frontend code (beware of legal ramifications) or implementing your own post UI.
While it's nearly impossible to change the state of React component from your plugin, nothing stops you from emulating user's input by sending keystrokes, mouse clicks etc. The only thing you need it to figure out - which DOM-element listens to these events (not necessary one of those 4 in you question).
About the possibility of direct state change: let's say the component you need to changes is a functional one. Then it has a form of
Component() {
const [state, setState] = useState(...)
...
setState(something)
...
}
so you need to somehow access the setState function of the component. But how? It's private to the function call. If you think that instead you can call the useState directly, then be aware that in another component it will return another setState. I have no idea what would happen if you'll call useState outside of a component, but surely it will not be able to guess which setState you want.
If you want you can check the source code of react-devtools to find out how you can dig out the state from the depths of React... but would you really want to try? And for what? The next time Facebook or React will be updated your code will definitely break.
I have been working on putting together a module to allow a user to invite their friends to use an app. Code works without major issue, but since I have over 100 contacts in my phone, the speed is rather slow. Scrolling isn't a problem, and I can add a loader as the phone pulls the data. But I when I choose an element for highlight it takes a few seconds for the item to get checked. I'm curious if anyone has any tips for how to optimize?
My snack is below:
https://snack.expo.io/#fauslyfox110/testingreferrals
Main file: inviteScreenTwo.js
React will update the elements on screen whenever you make it change to your state. In your case, I suspect that the delay is due to React going through all the contact records your showing and updating them when you change the highlighting.
One way of dealing with this is to make sure that contacts that are off-screen aren't actually in the DOM. You would need to update your render method to place only contact records in the list that are actually visible. That way, React won't need to update as many elements. Please refer to the React docs to read more about this optimization.
Another way would be to override the lifecycle method shouldComponentUpdate for your record components, making sure that the only rerender when their highlighted status changes. This is called reconciliation avoidance. The method has the following signature:
shouldComponentUpdate(nextProps, nextState) {
}
By default, this method always returns true. You could change it to compare nextProps with this.props, checking that the highlighting has changed, and return true or false as appropriate. Read more about this optimization in the React docs.
I am trying to set the focus on my React page but it doesn't work because the component updates which I think overrides the componentDidUpdate.
is there another way to do this?
this is the code I normally use to focus
document.querySelector("#input-box").focus();
If you are using react you should ideally be using refs and using them to set focus. Check the accepted answer for Set focus on input after render
If you have a problem of the component losing focus a lot, this can happen if the key value that you set for the component is not unique. React uses the key value that you set to track components across render cycles. If the key is generated incorrectly then you can have a scenario where the component loses focus across render cycles. For e.g., a controlled input box when a user is typing in it.
I want to ask, that is it possible to make an action on a div that scrolls to itself when it appears.
Environment: I use vue / bootstrap-vue in the client side, and I use alerts to inform the user. I made a vue component for that, and if something happened dynamically change the text, variant and the show attributes, to appear the information. However many sites are too big, so I wonder that in scrolling up, every time, whether the show attribute of alert component changes to true.
I found a pretty awesome component for scrolling (vue-scrollto)
but it is not for this problem.
I thought I made a watch on the show element and run this: scroll(0,0); but it was not so smooth, and it always go to the top, not to itself.
What do you recommend me?
I'm new to Ember and have a leaking state problem. I have a carousel widget that displays one item at a time and allows the user to click previous/next to see each item.
Here's the simplified carousel's component:
<button {{action "nextItem"}}>Next</button>
{{carousel-item item=selectedItem}}
Clicking next changes the selectedItem property so the next item is shown.
What I've realized is that the carousel-item component isn't re-initialized every time I move to a previous/next item. The DOM is reused each time, and the component's properties are shared since it's all one instance, which means I can have leaking state.
The alternative I see is to render all the items initially, so each has its own instance:
{{#each items as |item|}}
{{carousel-item item=item}}
{{/each}}
and to hide all but the selected item using CSS. However, this option kind of feels like a jQuery hack -- seems like Ember would have a better way. And I'm only ever showing one item at a time, so I hate to have so many extra DOM nodes when I don't need them.
What is the recommended way to handle this kind of a UI, where you only need one item shown at a time but don't want to share state between items? I'd imagine I should have one instance of the carousel-item component per item, instead of sharing an instance across all of them. But it doesn't feel right to instantiate every single carousel-item at first either. And I can't imagine the Ember way is to worry too much about the DOM details myself (determining which one is shown/hidden based on a class and some CSS).
Firstly, whatever framework or library you are using, jQuery, ember, angular, react, they are just a pack of JS/HTML/CSS right? So you should think in it's way, there is no magic!
So of course 1 component will only create 1 instance. If you just changed it's property(item in your demo), it just changed the property of an instance, other properties of it will remain as it is and triggered re-render. You cannot expect more. You have to manually reset other properties.
And yes, rendering everything by {{each}} looks stupid, but think about it, how could you create a smooth carousel animation by render only one DOM? At least you need to render 3 (current, previous and next) right?
Since carousel is a common UI, I recommend you to check existing ember addons fist before you write by yourself: https://emberobserver.com/?query=carousel
If I understood your problem correctly, the willUpdate hook in Ember.Component class should help you out. I this hook you can clear up the attributes, remove DOM objects, or anything at all. This will be called each time the component is about to re-render itself.
A simple example is of form:
willUpdate() {
Ember.$(this.get('element')).empty();
},
This will clear the DOM on each re-render forcing it to redraw elements.
You can try out other hooks too and see which event will serve your need. All of them are very helpful and serve different purpose.