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.
Related
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.
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
When rehydrating, React will complain when the initially rendered markup doesn't match the server markup exactly. It is however not entirely uncommon for certain components to not yield identical results clientside and serverside. Most trivially, consider a component that displays the current time:
function Now() {
return <span>{ new Date().toString() }</span>;
}
Obviously such a component would show a different value every time it's rendered, and as such React will always warn about incorrect checksums.
How can I tell React that it's okay if the client renders something differently from the server, for specific components?
To answer my own question, since React v16 the documentation says this about it:
If you intentionally need to render something different on the server and the client, you can do a two-pass rendering. Components that render something different on the client can read a state variable like this.state.isClient, which you can set to true in componentDidMount(). This way the initial render pass will render the same content as the server, avoiding mismatches, but an additional pass will happen synchronously right after hydration. Note that this approach will make your components slower because they have to render twice, so use it with caution.
All:
I wonder if I want to do data visualization using React JSX or Angular template to replace D3 DOM manipulation (such as .enter().append() .exit().remove()), how can I implement the animation transition like .transition().duration() in either of them?
For example, I build a line chart, in d3 after I change data set and generate new path, there is animation for those line to transform
Thanks
So, the problem with using D3.js in React is that both want control of the DOM, right?
D3 wants to directly select elements, add elements or remove elements based on the data being used, and add attributes to those elements.
React likes to have everything represented in it's virtual DOM and doesn't like any changes to the actual DOM without it's consent.
After some research, some people try utilizing some of React's different life cycle methods to instigate specific D3 methods at different points in a components life. For example, one approach wants you to return false to ComponentWillUpdate and use functional side-effects to run the D3 code on the actual DOM. While this works for some cases, it's still an improper use of React, and you're losing out on the benefits of passing state to any children components that component may be rendering.
I would suggest researching some of these approaches of how people have tried to tackle the issue, to see the root of the problem.
Also, feel free to try out this library my friends and I made that allows you to plug in your existing D3 code as is, and returns React components, and handles transitions, animations, timers, etc.
http://react-d3-library.github.io/
Always looking for more feedback!
newby alert
I am trying to use a contenteditable div in a react component hierarchy. I am hoping to use reflux instead of flux as I like the way one sets up actions and stores better in reflux (much less boilerplate, more features).
However, I am having an issue with contenteditable divs with an onInput handler attached. I'd like to keep my store up to date, so any onInput that occurs sends an action to the store, updating a field storing what is in the contenteditable div.
See the following gist, https://gist.github.com/dcnieho/0525f1becf1838616f5d, where test.js has three different ways to use an external store, changes to which lead to a setState at the top component, and this state gets passed down as props.
Using modes 1 and 3 (flux, or very simple handrolled version), things work fine: when i bash keys as fast as i can, the caret stays where it should be. When using mode 2 (reflux), the caret position will jump to the beginning of the content editable div every now and then. What i see in the log generated by my code is that the props coming in are behind the DOM content as accessed by the innerHTML through a react ref. That triggers a rerender of the contenteditable div, changing its innerHTML.
Note that things work fine with flux even when commenting out the shouldComponentUpdate function at line 92 and the componentDidUpdate at line 105, which were styled after this answer. The same problem occurs when these are commented out in mode 2, reflux.
It thus appears that rerendering per se is not an issue (else all methods would have a problem when commenting out shouldComponentUpdate), but rerendering and putting a different innerHTML that what is at that moment in the DOM into the contenteditable div messes things up.
One further insight into this is the following. I log messages to the console indicating when things of interest happen. With vanilla flux, bashing keys, I get a nice chain of onInput being called, dispatcher called, render train, next onInput called. With reflux, i may get onInputs anywhere, before render train is finished, or even before the dispatcher (well, action/store its called in reflux) is called for the previous onInput. It seems like some things happen asynchronously in reflux where they shouldn't for my use case?
Am I doing something wrong? Is the way in which event happen in reflux not suitable for what i want? Is there a better way to approach content editable divs in react+flux? Are there important concept I seem not to understand (I am a newbie)?
Ok, turns out this was a RTFM situation: reflux gives you the option of having actions triggering the store synchronously or asynchronously. The default is asynchronous. Reflux actions have a triggerAsync and a trigger method, where the former is called by default, but the latter can be called directly or set as the default when creating the action.
Synchronous handling of actions solves my problem, not allowing the DOM to get ahead of the event processing.