Here is scenario:
react renders components
external library changes dom structure and move a part to somewhere else in dom not handled by react
Result:
Every events set are not working anymore and exceptions..
Expected
Events (clicks) work
What do you think about it ?
Is it possible with react to rerender everything based of a new dom structure ?
Dom react structure is really changed, some part have moved somewhere else in DOM
Thanks,
Julien
Related
Some situation
I am currently using the js library code-mirror (v5) (a text editor with some nice features, such as syntax highlighting) and i must add widgets to it using its API.
It is quite straightforward, you just give code-mirror's API the html element you created for the occasion and it will add it to the page document inside the dom it generated for the editor.
So i just mount a new react component on the HTML element i fed to the code-mirror API. It is correctly rendered without errors, but...
The Problem
While the method above works I'm quite sure that's not the way to do it for multiple reasons.
The created component lose the parent context (so change to props doesn't update the created component & stores such as redux are inaccessible)
It breaks from the app react tree
It is not cleaned up with the destruction of any component and will just remain in memory until we use ReactDOM.unmountAtNode()
I tried stuff with portals but it doesn't seems to be what i need in this case (if i got it right portals do render things outside of the react tree)
Example
This an example of a method that would add a react component to the codemirror as a widget
function addWidget(component: ReactElement, position: Position): void {
const div = document.createElement('div');
ReactDOM.render(component, div);
//code mirror api
editor.addWidget(position, div, false);
}
Conclusion
I am looking for React best practices in these cases where components needs to be mounted on dynamically created HTML element without losing context and still being attached to some part of the app react tree.
Thank for your time.
Is it possible to reference existing HTML element in React?
I have a page where React used only for small part of components and I have "video" element that exists on page before React loads. Then I have a react component which have a couple of props that should affect video element.
What is the best/correct way to achieve this?
Currently, in render method of a component, I use document.getElementById('video-' + this.props.videoId) and then manipulating it. I thought that I can somehow use "refs" to say to reuse the existing HTML element, but not sure how and didn't found useful information.
Thanks!
What I understand is, you have an app, probably built in some other stack and you are trying to use React inside that app. The page is loaded before and then the React component renders. As pointed out by Icepickel, refs are for the components that are created by you inside the React app. So, you can't use that here.
Normally, it is discouraged to directly access the elements in the DOM. But since you are using it on a part of it, so it is totally fine. But doing it in the render() method is not the right choice here.
Instead what you can do is, utilize the React lifecycle methods to control the video player in a better way. Normally when a component is mounted on the DOM. Following lifecycle methods are called in the following order:
constructor
componentWillMount
render
componentDidMount
So, what I will suggest is, inside the constructor set the state using document.getElementById('video-' + this.props.videoId). [I am assuming the page laods before the react component].
let el = document.getElementById('video-' + this.props.videoId);
this.state = {
videoPlayer: el;
}
And then later when your component is mounted. Inside the componentDidMount, change whatever you want to change in the video player.
I have also created a small Code Sandbox Sample to elaborate on the lifecycle methods. This way, you will be able to write cleaner code and easily manage the state of the video player.
is it true, the purpose of Ref is replacing document.getElementById??
Once i apply react, i should not use document.getElementById to access DOM to get data?
i found some article said that we can apply the this.refs to access the DOM
<input ref="test" value="option" id="option4"/>
console.log(this.refs.test);
But it can only run within the method within the component,
what if i want show the input value in console (developer Tools)?
It is true in a way, because react uses its virtual dom and diffing algorithm to watch changes and reflect in dom. If you use direct api to access dom. react could not access it in its virtual dom.
Thats why they have an unique id or keys just like in DOM to manipulate elements (components) as node.
If you see in confirm-alert components used in npm packages, they will create an element and render it as an element by using ReactDOM. As soon the toaster is finished it is not removed directly from the DOM.
First it is made to be find from the reactVirtualDom by using api findDomNode at https://reactjs.org/docs/react-dom.html#finddomnode
then it is unmounted using unmountComponentAtNode.
https://reactjs.org/docs/react-dom.html#unmountcomponentatnode
For example: https://github.com/GA-MO/react-confirm-alert/blob/master/src/index.js
So, refs are used to overcome direct DOM manipulation and changes that affect or effects the react rendering process.
I just started to learn ReactJS. I was used jQuery and Javascript for all my projects previously and got few doubts on ReactJS after gone through tutorials.
Why I need ReactJS, still jQuery is there to update DOM and handlebar, dust is there to handle templating.
There's a concept Virtual DOM,In tutorials I can see it will take a copy of my DOM and updates only needed. Anyone please explain how it's differ normal DOM manipulation.
In React all event handlers are inline, <input onClick={this.eventSample} /> is this recommendable ?
I just started learning,If anyone clears me these doubts with some practical code example. It would be helpful for me to proceed further in React.
Thanks in advance.
With my understanding I'm explaining to make you understand :
Take an example of list times :
If one of these list items updates, then the DOM re-renders the entire list. This is where the DOM’s inefficiency stems from.
Ideally, we’d like to only re-render items that receive updates, leaving the rest of the items as-is.
React’s use of the Virtual DOM helps to reduce this inefficiency.
Normal DOM Manipulation :
Checks through all node’s data at a regular interval to see if there have been any changes.
This is inefficient because it requires traversing every single node recursively.
React's virtual DOM:
Components are responsible for listening to when an update takes place.
Since the data is saved on the state, components can simply listen to events on the state and if there is an update, it can re-render to the UI.
light-weight abstraction of the DOM. You can think of it as a copy of the DOM, that can be updated without affecting the actual DOM.
In fact, a new virtual DOM is created after every re-render.
When updates are supplied to the Virtual DOM, React uses a process called reconciliation — using a “diffing” algorithm that compares/contrasts changes in order to know what updates have taken place.
React then only updates those elements that have changed, leaving alone those that have not.
I hope this helps to shed some light on the advantages of efficiency with React’s use of a virtual DOM.
more at Why is React's concept of Virtual DOM said to be more performant than dirty model checking?
React, it’s so much more than a templating engine.
The JSX is, therefore, broader then template engines.
Hope you know how template engines work. here’s the comparison :
JSX/JS: javascript -> vdom
Template: string -> javascript -> vdom
// File 1 - templates/progress.html
<div class="progress-container">
<div class="progress-bar" data-style="width: $val"></div>
</div>
If you look at the template code, and the component separately, how can you tell where $val comes from?
// File 1 -- progress
const (val) => (
<div class="progress-container">
<div class="progress-bar" style={{width: val}}></div>
</div>
);
In this example, it is perfectly clear where val comes
more at https://stackoverflow.com/questions/32619168/react-engine-vs-other-template-engines
JQuery and React solve two completely different problems.
jQuery interacts with the DOM directly.
The idea is that DOM elements carry around too much unnecessary data, and the virtual DOM abstracts the relevant parts, allowing for faster performance.
In React, you modify the virtual DOM, which it then compares to the existing DOM elements and makes the necessary changes/updates.
Inline Events :
I can understand why you asked this, In HTML DOM you use inline events as “bad practice”.
Here, In React With JSX you pass a function as the event handler, rather than a string.
When using React you should generally not need to call addEventListener to add listeners to a DOM element after it is created.
Instead, just provide a listener when the element is initially rendered.
This is actually a React pro.
Hope I cleared your doubts as much as I can
I have a JS code which should do some things (animations etc.) BEFORE ReactJS possibly (or not) will update HTML element. I'm getting the whole template for this HTML element (i.e. part of the page, in particular a widget) for this purpose.
For example, I have a DIV with some content, which may change in time or not. Then I get a new version (i.e. as HTML template) of that DIV through AJAX call, and I want ReactJS first to compare the actual (or virtual) current DOM with the one just retrieved new HTML template for the same DIV in a string as got from AJAX call on success. Only then - when these two are different - it makes sense to do animations first, and only then update the actual DOM in the browser by React JS.
How to do that? Is there a method in React JS that allows me to get e.g. true/false when comparing virtual DOM with its new version as a HTML template got through AJAX (since it does internally this thing anyway - i.e. comparing current and updated DOM in its algorithm)?
EDIT: Hmm after initial thought that ReactJS is way much better than other JS Frameworks in my case (i.e. server functionality is already developed), I found multiple features not flexible enough; further more, I found ReactJS is not smart enough to figure out that only one element at the top of the list is added (ReactJS replaces the whole DOM template for the list, even with keys set for each element!), which suggests it's still not that mature as one could expect.
Besides, all Lifecycle methods with ***Component***Update are not called; only ***Component***Unmount are being called in the case of mentioned list. I can do it in a simpler way by myself, however Relay / Flux + ReactJS architecture is still nice, and I think I'll just abandon Facebook's implementation, and replace it with my own solution, inspired by Relay/Flux+ReactJS.
You might want to look at the following life cycle methods:
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
From the react docs:
componentWillUpdate
Invoked immediately before rendering when new props or state are being received. This method is not called for the initial render.
Use this as an opportunity to perform preparation before an update occurs.
componentDidUpdate
Invoked immediately after the component's updates are flushed to the DOM. This method is not called for the initial render.
Use this as an opportunity to operate on the DOM when the component has been updated.