Almost in every ReactJS tutorial or even in the official documentation for handling input changes, onChange is recommended. We use a state for the value and change it via onChange. This triggers the render in every key stroke. So,
Is rendering really that cheap?
Is input value not being held in DOM? So there is no difference between the DOM and VirtualDOM, so although the rendering happens nothing changes? (Wrong assumption probably).
Just for fun and learning purposes I tried those:
Used a custom function and variable to hold the value, set the state after last input not for in every keystroke, passed that value related component etc.
Used onBlur instead of onChange.
But, I don't like either of them and want to ask this question. If live input value changes is not important for us, we only care for the last input, still onChange is the way to go?
React handles the re-rendering very efficiently.It only re-renders the changes.
There are two ways to configure the inputs
First: Controlled Input
With a controlled input, you specify the value of the input with a state variable generally(or even a prop in some cases). In this case you need to call the onChange function to set the state(or the prop) since the value is set to a state/prop and you need to change that to change the value otherwise it will remain the same.
Ex
<input value={this.state.textVal} onChange={(e) => this.setState({textVal: e.target.value}) />
The advantages of having a controlled input is that you have the value available throughout you React component and you do not need an event to be fired on input or access the DOM to get the value.
Second: Uncontrolled input
In this case you don't need an onChange handler to get the input as you don't specify a custom value for the input. The value of the input can be fetched by accessing the dom or from an event object
Ex:
<input type="text" onBlur={(e) => {console.log(e.target.value)}/>
The other way to get the input value will be by accessing the DOM which we do using refs as this.inputVal.value
See this answer on how to use ref:
In React .js: is there any function similar like document.getElementById() in javascript ? how to select certain object?
Regarding you question on React virtualDOM
The virtual DOM is used for efficient re-rendering of the DOM. This isn't really related to dirty checking your data. You could re-render using a virtual DOM with or without dirty checking. There is some overhead in computing the diff between two virtual trees, but the virtual DOM diff is about understanding what needs updating in the DOM and not whether or not your data has changed.
Virtual tree is re-renderd only when the state changes. So using an observable to check if the state has changed is an efficient way to prevent unnecessary re-renders, which would cause lots of unnecessary tree diffs.
For me, the major reason to use controlled components, aside from real time validation, is the principle of "Single Source of Truth."
In the case of an uncontrolled component, the value of the input may be different between the form input and the one used in your React component. You may fetch the new value onBlur, but there are ways that the value in DOM can change without emitting this event, and in that case the value that the user sees and the one that you are working on may differ, resulting in a different result from what the user expects.
This may not be a huge concern, but since React preaches this principle a lot (like not keeping values in state that can be derived from other states), I'd just do it for the sake of consistency.
Besides, you do not need to worry about the cost of re-rendering on each input.
Related
I'm working with a form that may be a bit over-engineered, and I'm trying to write a script to step through the form and submit it. Most of the form is pretty hackable, but there's a 3-part date input which is just not responding to my attempts to manipulate it programmatically.
The date field works, if I click or tab to it and begin typing. But if I manually dispatch events, even ones that are identical to what it receives when I type and have exactly what the code seems to be looking for, I can't get it to hold onto its values and perform validation. I've tried a lot of variations of this. I've tried manually dispatching a custom event that matches a custom Vue event it should be listening for.
Is there a way to instead manipulate the data of the Vue component directly? To force it to have a certain "monthValue" for example, without intermediate events? I don't expect that there is, but hopefully I'm missing something. Please note that I do have the ability to refactor the form, but that should be an absolute last resort.
As far as I can tell, no, there isn't a way to do this. But it wasn't necessary.
The solution involved being more careful in looking at what the components were actually trying to do. In this case they were input elements using v-model, which is shorthand for a combination of #input (event listener) and :value attributes[1]. This meant that dispatching synthetic input events with the correct data attribute could convince Vue to accept the value and retain it (whereas any value dispatched in any keyboard event would be ignored entirely). This only addressed half of my problem with this particular form, but it is the correct solution for the question asked.
[1] https://vuejs.org/guide/essentials/forms.html
I am new to React and a bit struggling with state in React and how and where we need to use it. So far, I found out that "If modifying a piece of data does not visually change the component, that data shouldn’t go into state". So, state is all about re-rendering the UI(I hope I am correct). So, the question I want to ask is Is it true that we use state only for re-rendering the UI only?, nothing else and nothing more?
You can use state in your class components. State is like private data of your component that may change by action made by user.
State is immutable. This means you can not change state directly in following way this.state.someVal = "smth". The only way to change state is using this.setState() method.
When you change state value React automatically re-renders your component without refreshing the page. In other words React.js reacts to your changes
State is an object that is directly tied to rendering the component. The reason why you can't change State directly with say this.state.foo='bar' is that React would have no way of knowing that it needed to re-render the component if you did that. Thus there is a setState method to change the state, which under the hood calls the render function of your component.
Therefore, if you have some data that has nothing to do with rendering the component, you don't want to put it into state, as setting its value will cause unnecessary renders to occur. If you're using class components, you can just put that data on the class directly: this.foo='bar'.
Basically yes! Two examples might be: A - holding a list of items (shopping list, or todo items) that are rendered directly to the UI, that are subject to change as the user adds and removes items. B - a value that determines whether or not you want something to show up on your UI, for example, you might have a state value called 'showNavbar' that is either true or false, depending on whether you want the user to see a navigation bar.
I hope that helps make sense of it in a basic way :)
We use the state for rendering the UI.
Also, I think the State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.
For this, We use the 'setState' method.
setState() is the only legitimate way to update state after the initial state setup
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 have been using React from couple of months and React doesn't simply re-rendering a component completely instead it finds the difference and makes those changes. Does Angular 2 does something like this?
And also whenever a change in state is detected does Angular 2 re-render all the components from the root node or does it only re-render those specific components and their sub-tree whose change is detected?
React doesn't simply re-rendering a component completely instead it finds the difference and makes those changes. Does Angular 2 does something like this?
Conceptually yes, it does not re-render entire components.
Angular builds a change detector object for each component/directive. Template bindings (which includes input property bindings) are tracked inside these change detector objects. When change detection runs, by default, each binding is dirty checked for changes. If a change is found, the changed value is propagated to the child component (if an input property changed) or to the DOM. That's it. The entire template/view is not re-rendered. Only the changed values are updated in the DOM. When Angular change detection finishes, the browser notices the DOM changes and updates what we see on the screen.
whenever a change in state is detected does Angular 2 re-render all the components from the root node or does it only re-render those specific components and their sub-tree whose change is detected?
Angular doesn't detect changes to some model/data objects. Rather, it only detects changes to template bindings.
By default, each time change detection runs, it starts from the root component and checks all components for changes, in depth-first order, using those change detector objects. As described above, only template bindings with changes are updated. So, I wouldn't say that Angular ever re-renders a component... it only modifies those parts of the DOM where a template binding changed.
You can configure a component to use the OnPush change detection strategy to limit when that component and its descendants are checked for changes. You can also completely detach() a component from the change detector tree, which means that component and its descendants will not be change detected until you reattach().
Angular is not using virtual DOM as React do. No need for that in context of Angular.
If you have <input> and need to set its value in runtime to something else you don't need to change all DOM around it. You just call setValue() on that element and that's it.
The same applies to any other DOM element. For example if you have this:
<div>{{someVar}}</div>
and Angular detects that someVar was changed it will change content of only that particular <div>.
Angular only renders where it detects changes.
AFAIK there is some room for improvments in *ngFor where it sometimes re-renders too many items when some are added/removed in the middle or the beginning but that is a known issue and will be fixed eventually.
From my comment below
In fact Angular doesn't need re-rendering optimization because it only does anything when bound values change and then it only changes the DOM where it is bound to the changed value. Angular doesn't have a virtual DOM that it needs to mirror to the actual DOM.
Angular2 is using zone.js for onChange rendering. Usually when a change is detected, it will trigger changeDetection that component and all the children, but you also can have control to change that, to force render some things or not render when you don't like angular2 behavior.
Here is a very good talk about how Angular2 change detection works : https://www.youtube.com/watch?v=CUxD91DWkGM
LE: Just to clarify, it will not re-render the component and all the children, it will detect and trigger changes for all of those, but will render only what is necessary.
I see a lot of examples using React with backbone, there is however some things that are still somewhat unclear to me. In nearly all examples they show how you can get your component to listen to a model or collection and update the view accordingly, this seems pretty straightforward, you can use the Backbone Mixin or you can setup some event listeners in "componentDidMount()".
What is unclear to me is how to handle the other way, ie when a user writes in some input field, I then want to set this same value on my model, which ultimately is what i validate and then save on the server.
With simple forms this is also pretty straightforward, you can have a callback for the onChange event, example:
return <div><input type="text" onChange={this.setPrice} /></div>
All good, in the setPrice function I can now do something like:
this.props.myModel.set('price', e.target.value);
This works, but two things that immediately strike me:
The set method will be called on the model every single key event, since Reacts "onChange" actually executes on every key event, when you type in the textbox.
My second concern is, this works good for simple forms, however we have forms that have upwards 30-40 different input fields, having an onChange event on all of these input boxes, checkboxes and what have you seems counterproductive.
Right now, we have a databinding in our Backbone Views that simply sets whatever the user types on these input fields on the model, this does not seem to be the way togo in React though since what would be updated if you use something like ReactLink is the properties inside "state" on the Component, not properties directly on the model.
Is there a best practice here, or is this "marriage" between React and Backbone simply not meant to be? It would seem as if you would need to somehow map each input field to a specific property on the model. I am not sure if this is a good thing todo with React.
Thanks
You can call the setPrice method onBlur instead of onChange so that you will update the state when the user clicks or tabs out of the field.
This is more efficient for longer forms in my opinion as you are guaranteed that the user will tab or click to the next field.