React Multiple Text Inputs Controlling Each Other State - javascript

Working CodeSandbox Demo
So I'm learning to use React, and trying to create a currency exchange app.
I'm having a problem understanding how to setState from multiple inputs depending on the input you're actually using.
I set up a CodePen to show you what I'm trying to do.
Things I know or don't:
Right now I'm only updating a tempValue state.
If I use the first input field it gives me the desired effect.
2.1 I know in this case I'm not updating the states, I'm just doing my math right on the value prop (but it works to show my intention).
2.2 I don't know if I should do the math on setState or on a separate method.
2.3 I can probably use a wait timer and look for onKeyDown then setState.
I could probably use uncontrolled components, but it wouldn't be the React way (is it a bad thing).
My setState originally used [computed properties] for the name but changed it for demonstration purposes.
Working CodeSandbox Demo

Since you have access to the input in your onChange function, you can get the input name off event.target and use that to make modifications in your state.
Alternatively you can bind the function:
<CurrencyInput
onChange={this.handleCurrencyInput.bind(this, currency.name)}
/>
But this isn't the best to do in your render, so you could make a renderCurrencyInput method on your class and bind once there
Computed properties would work, I don't see much of an issue with it. Then you can drive your initial this.state from your list of currencies

Related

How to do onClick element change in Redux a container with React.js?

I already saw a similar question from someone else here and the answer is pretty clear. Yet, if you're working with in a redux container, the states turn into props through the mapStateToProps function.
How is it then correct to proceed if I want e.g. my text-div to turn into an input, when I click or double-click on it? I don't have any code yet, I'm wondering about the theory.
The components get store state data passed in as props, but they can also have their own state. So in your case, your component would use it's own state to handle the toggling of div to input. If for some reason you wanted it to be saved in the store instead, you would fire off an action to toggle the view and then use the prop from the store in your render method.

What constitutes an appropriate use of ref in React

Can someone explain how ref is used in React? I understand it's a shortcut that sort of defeats the purpose of the react DOM, but I don't know how or why exactly. I'm trying to determine whether something I'm trying to accomplish represents one of the rare cases where you should use ref
I want a custom bootstrap alert I can show from any of these pages, without using JQuery (I have one working with JQuery already)
I have a router that switches between pages, each containing a Layout component with a Page component inside (based on this)
Like:
render() {
return (<Layout ref={layout => (this.layout = layout)}>
<WhateverPage
session={this.session}
otherExampleProp={"something"}
showAlert={this.showAlert}/>
</Layout>);
}
showAlert(type, text, hasTimeout, timeoutMs) {
this.layout.alert.showAlert(type, text, hasTimeout, timeoutMs);
}
I can think of three solutions:
Use ref, which as I only partially understand defeats the purpose of react components to some extent, but I'm not sure how exactly...
Use ref, but to a lesser extent, by placing the alert component in each Layout before the Page component (so no need for a ref to ).
Create a component and a function on each page, using the page's state to control the alert, so it would be basically the same as creating a unique alert for each page, which also defeats the purpose of a component...
The example most people give when explaining what to use ref for involves focus() - is this similar? Intuitively it feels like I should use ref, but I also know that theoretically you shouldn't, but I want to understand why, because there are exceptions and for all I know this may count.
Similarly, I want to create a confirm component to replace the native JS confirm() (since it might be deprecated soon), and this approach (using ref) also makes this WAY easier than creating a component for each page, since I can pass any function as a parameter to the confirm component for it to execute on an OK button press (also gives me the option of including icons, titles, custom buttons, etc).
Existing examples and libraries all seem to use method 3 (or they're simpler, and not not really analogous).
Is ref ok to use here? Is it wrong? Why? Am I overthinking this?
Yes, you are "misusing" ref here because you're trying to build around how React is intended to be used.
ref is mainly for accessing the actual rendered DOM element - maybe to focus it, read input, get dimensions, whatever. Generally speaking though you should us ref as a "read only" feature - use it to get info about the rendered DOM but don't use it as part of a process to bypass render() or inject elements into the DOM.
What you should do is create a reusable component for your Alert. Make it flexible enough that it can accept arbitrary settings like color, text, duration, callback functions for accept/cancel/clear, etc. Then you can just render it somewhere, maybe like this:
<MyAlert
title="foo"
text="bar"
duration={5}
confirmCallback={someFunction}
cancelCallback={anotherFunction}
/>
Remember that components are a way to render and interact with state, and that's exactly what you're trying to do with your Alert. There is some kind of notification, it has content and controls for doing some action(s), and all of that should live somewhere in your app state hierarchy. There is absolutely no reason to resort to refin this situation.
To complement the jered answer:
If you plan to use the alert component in all the pages then instead of placing an alert component inside each page you can create a high order component named like PageWithAlert (I would say just Page) that includes the alert component for each page.
You might want to take a look at this https://facebook.github.io/react/docs/higher-order-components.html

How to disable data observation in vue.js component property

I want to create a Vue.js component that receives properties from its parent component, e.g.:
<table-cell :value="foo" format="date" />
Because value and format are defined as properties, Vue will automatically register observers to their values. That is fine in general, but for my use case I positively know those values are not going to change so they don't need to be observed.
Given that my table cell component can be in a table with, say, 1,000 rows and 10 columns, those 2 properties will create 20,000 observers, and I want to avoid all this overhead (and my real table cell component has more complex properties).
Is there any way to disable a component property from being observed in order to avoid wasting CPU & memory resources?
Update:
I have found a low-level solution with the functional component approach, explained here: https://v2.vuejs.org/v2/guide/render-function.html#Functional-Components
I have tested it with this JSFiddle: https://jsfiddle.net/50wL7mdz/12143/
I wonder if that is the correct approach...
Pass it with custom data I think like <your-component :data-value='foo' :data-format='date'>
It will do what you want.

React Form controlled by a Flux Store (Best practice?)

So I have a big component that would be my form:
<form>
<FirstComponent value={this.state.firstValue}/>
<SecondComponent value={this.state.secondValue}/>
{more components here}
<input type="submit" ... />
</form>
This form component is listening for a store that updates its values using firstAction, secondAction, etc.
Note: Component updates its state based on store.getState() that returns {firstValue: something, secondValue: something, etc}
So let's say my FirstComponentis an input:
<input type="text" value={this.props.value}
onChange={(e)=>this.props.firstAction(e.target.value)}
</input>
Ok, so the onChange fires the prop firstAction which is actually the Flux action that will update my store and make the form to re-render. I have two good things here, when user submits the form, I can check the value of FirstComponent in my store and I also control all my state from the parent component.
However, this onChange callback will call an action every time the user types one character (so it can produce a lot of calls therefore re-renders) <-- can this provoke serious performance issues?
Instead, I could use refs and when the user press the submit button, get this.refs.myFirstComponent.state... and I will have the value too (that would be Uncontrolled Component?) But this does not sound like a recommendation from the community.
So my question is, is the first approach I described above a good way to go? How can I optimize it? So a re-render that should only affect FirstComponent does not make SecondComponent and so on to re-render? Is shouldComponentUpdatethe only way to go here?
Edit 1:
With the first approach I am facing a problem... I have an e2e test using WebdriverIO adding a value into the text field: http://webdriver.io/api/action/setValue.html
I don't know why but if I am trying to add the word "Testing" into the input, webdriver will only add the last letter. This problem is gone if not using state/store at all. However, if I have the state internally to my FirstComponent, something like:
<input type="text" value={this.state.value}
onChange={(e)=>this.setState({firstValue: e.target.value})}
onBlur={()=>this.props.callback(this.state.firstValue)}
</input>
In this case, component seems to react faster while typing (only renders itself), and then, when user removes focus it updates the store. I have to say, I don't like this approach because it doesn't follow the pattern of take your state up (and I feel I am duplicating the state) BUT it seems to work faster and more important: My e2e test works. Any more ideas?
Your first approach (i.e. onChange fires flux action which updates the store and make your form re-render) seems like a good way to go. I've been using it like that and I've seen other people using it like that, too.
Regarding your following comment:
However, this onChange callback will call an action every time the user types one character (so it can produce a lot of calls therefore re-renders) <-- can this provoke serious performance issues?
Yes, I believe so. I once created a component that contains many other components along with some input fields. Whenever I typed a character in an input field, the whole component (with other components it includes and the input fields) got re-rendered, causing the performance problem. It was noticeable if I typed fast. You can actually verify it using https://facebook.github.io/react/docs/perf.html.
Anyway, how I got around the problem is, as you mentioned, by implementing shouldComponentUpdate().
A small tip I'd like to mention is creating a custom <Input /> component that wraps around <input /> and implementing shouldComponentUpdate() (i.e. this.props.value !== nextProps.value || this.props.checked !== nextProps.checked) That way, if you create a form component, for example, with many input fields (using the custom <Input />), only the input field that is changed gets re-rendered.
I'd love to see how other people approach this problem, too, though.

React.js: Why is there no componentDidRender event?

I have just started using React, and a couple of times I have thought to myself: "Why is there no componentDidRender event?".
Say that I have a component that renders a table to the DOM, and I want to use bootstrap-sortable on this table to allow the user to sort on whatever column he wants. In the case of bootstrap-sortable you need to run $.boostrapSortable() after the table is drawn, in order to initialize the plugin.
As I see it, there are two handlers on a React component that would be logical to consider to use for this purpose:
componentDidMount: This does not work because the DOM does not seem to be updated at this point of the execution.
componentDidUpdate: This could possibly work, but it does not fire on the initial render.
I am not saying that React is actually missing a componentDidRender function, because I assume that there is a perfectly logical explanation as to why it is not there. I am just asking if someone could explain why such a function is not present, and what would be the "React way" to handle a case like the one above.
In componentDidMount you can do: this.getDOMNode() to get a reference to the underlying DOM for that component. So if you do want to use your mounted component with jQuery you can do:
componentDidMount: function() {
$(this.getDOMNode());
}
http://facebook.github.io/react/docs/working-with-the-browser.html
Here's a fiddle which shows jQuery acting on the DOM node of a react component:
http://jsfiddle.net/sa5e88ys/1/
As you can see, it adds a border to the div as expected. If you're still having problems I guess it could be with the plugin you're using rather than jQuery or react?
Although there's no componentDidRender, you can make a method with the desired behavior and call it in both componentDidMount (which is only called after the first render) and componentDidUpdate (which is called after every render but the first).
Also, this is the preferred way of getting a ref to a DOM node from within the component:
https://facebook.github.io/react/docs/refs-and-the-dom.html

Categories