How to get value from a dropdown to a button? - reactjs

I'm using react JS and I have a problem. I don't know how to get the value from my dropdown and put that value into a onclick button. I have read lots of topics but I haven't find anything really useful for a beginner like me.
I am using "scheduler" that helped me built my dropdown and some other stuffs.
So, my dropdown get data from a local file and looks like this:
{values.map(v => (
<option value={this.value}>{v.value}</option>
))}
console.log(ref)
And my button is like this:
<Button onClick={() => this.decrement()}>
Ajouetr la réservation
</Button>
The decrement method was only there to test if it was working, and it is.
Actually, what I want to do is quite simple: I have some values in my dropdown (from 1 to 7). And I have a state that says there is 30 places available. What I want is when I choose a specified item in my dropdown AND validate with my button and then my state to decrement with the specified number. Because right now it only decrement with 1.
I hope it's clear enough for someone to help me, because I spent 2 days on that problem and I don't know what to do.
Thank you :)

Next time, it's nice to provide an interactive example with your question. Here's a CodeSandbox I made that (I hope) illustrates your example (link). If you want to fiddle with the example, just click "Fork" in the top right corner.
Back to the solution:
I think what you're missing is storing the selected value in your state along with the 30 "places". What you want is to make your <select /> tag into a "controlled component". When someone interacts with the <select /> you want to change the internal state so that it matches the selected value. That way, when you call decrement() from your button, you can use the internal state's value rather than getting it from a ref (I think that's what you were trying to do).
Here's a link to the React doc that explains how to use forms, specifically the <select /> tag: (link).
Take care!

I would say that you can think about this in 2 different steps:
SET THE QUANTITY STATE
Set the state with the current dropdown value - For achieving this, you can just use the onChange method in your select:
<select name="quantity"
value={this.state.quantity}
onChange={this.onSelectQuantity}
>
In your constructor, you create a variable quantity inside your state
Create a function called onSelectQuantity where you will set the quantity state with setState.
Do not forget to bind the function onSelectQuantity on the constructor.
With this, every time that you change the value on select, your state would capture its value. You can log it from the function if you want to test if it works.
DECREMENT FROM THE BUTTON
After this, you can just decrease the value of the state again from decrement function
<Button onClick={this.decrement}>
Ajouetr la réservation
</Button>
You will have a function...
decrement() {
const newQuantity = this.state.quantity - 1;
this.setState({
quantity: newQuantity
})
}
Hope it helps!

Related

why state updates on second time clicking in react js

I have a state which fills by name of empty form inputs. first time when you click on button it fills by some key but it is empty at all but in second time it fills by some key like "age" or other thing. Do anyone face with this kind of problem?
Check if this works:
<input value={age} onChange={(e)=>setAge(e.target.value)} />
or
setAge(()=>newValue);
if not, please share some code.

ReactJS - Checkbox doesn't re-render if click-handler is instance method

I prepared a demo on JS Fiddle to demonstrate the problem.
Please, have in mind that in my real world example I have a lot of custom logic - which I've skipped here - that's why some parts of the code in the JS Fiddle (may) look strange.
===
The problem - if you click on the labels - the wrapper and the inner components get updated and rendered correctly.
However - if you click on the checkboxes themselves - then the wrapper gets updated, but the checkboxes doesn't render correctly.
https://jsfiddle.net/dbjfvsm2/5/
At the same time - if I directly call the property handler from the checkbox - then all is fine:
https://jsfiddle.net/dbjfvsm2/6/
I tried with onChange as well, but same result.
Why is this happening? ... And I really need to have that instance method - onItemClick - that is reused by both the label and the checkbox, this is where some general stuff is happening.
The only thing preventing checkbox to being checked is e.preventDefault(); in onItemClick function. Try removing it and it will work.
onItemClick = (e, id) => {
this.props.handleCheckboxClick(id);
}
Why it didn't work? Your answer is here
I've updated your fiddle in order to get your desired result
https://jsfiddle.net/sabbin/kh4j1Ltp/12/
You should not use the verification in the child component in the first place, also e.preventDefault was causing the an issue in your logic. Also avoid using arrow functions inside the render, you could bind the eventHandler to the class it self
LE:
I changed the checkbox logic in the exaple to use a generator, but you can write them one by one
Instead of
{checkboxes.map((id)=>(
<Checkbox
handleCheckboxClick={this.handleCheckboxClick}
selected={this.state.selectedCheckboxes.indexOf(id) > -1}
id={id}
/>
))}
You can write them directly
<Checkbox
handleCheckboxClick={this.handleCheckboxClick}
selected={this.state.selectedCheckboxes.indexOf("item-two") > -1}
id="item-two"
/>
<Checkbox
handleCheckboxClick={this.handleCheckboxClick}
selected={this.state.selectedCheckboxes.indexOf(item-one") > -1}
id="item-one"
/>

React - Select multiple checkboxes holding Shift key

I have a list of checkboxes in my React App. When I hold Shift key and click one - the others between current and the nearest checked one should become selected.
For now I'm tring to do somethimg like this:
<input onChange={(e)=>this.handleCheckbox(e)} value={id} checked={this.state.selected.IndexOf(id) > -1} type="checkbox" />
handleCheckbox(e){
if(e.shiftKey){
console.log("shiftKey is hold")
}
//here goes some logic to save checkboxes in the state
}
But the condition if(e.shiftKey) is never executed. What am I doing wrong?
For future visitors:
To check if the Shift key is pressed, check the e.nativeEvent.shiftKey in the click event.
You still have to implement the logic for actually checking the boxes. If you need help with that, let me know.
Hope this helps.
onChange is trigged after you let the key up. You should use the onKeyDown event.

Opening the menu to the default value in react-select

I am using react-select to allow the user to choose their birth year. If the user has already filled it in, it will be preset to some value, e.g. 1950. The input shows the correct value, however when the menu is opened it is scrolled to the top and shows the most recent years (2018, 2017, 2016, etc).
How do I get it to scroll down to 1950 and highlight that item by default?
My code:
class YearPicker extends React.PureComponent {
options = [
{label: 2018, value: 2018},
{label: 2017, value: 2017},
// ...
{label: 1950, value: 1950},
{label: 1949, value: 1949},
// ...
]
render () {
return (
<Select
options={this.options}
value={this.props.value}
/>
)
}
}
CodeSandbox—this should default to 2002. Once you select a value (2002 or otherwise) it works fine, but when the page first loads you have to scroll down within the menu to find the value.
Per the docs I have tried value and defaultValue as well as selectedOption but nothing seems to work. I created a very hacky workaround by leveraging onMenuOpen to find the correct DOM element after it's rendered and then scroll to it, however this breaks the functionality of the arrow keys.
I looked at their source code and actually, you are doing everything right. The issue is in the following line of their code in Select.js:
const selectedIndex = menuOptions.focusable.indexOf(selectValue[0]);
Here they are determining the index of the default option using indexOf and comparing objects. Object equality is performed by reference and not by value. So when you initialize the component for the first time and you explicitly provide an object, the equality fails. Wrong option is highlighted only for the first time. Rest of the times, object equality works since they extract the selected object out of the options and indexOf works
Check the working fork https://codesandbox.io/s/0xzmy6wvln
What I have done is created a function that extracts the selected option from the options array and passes that and so the equality works even for the first time.
I would encourage you to raise this issue on their repo and try to get it fixed.
Set the default value to the object from the options menu.
<Select
options={this.options}
defaultValue={this.options.find(option => option.value === this.props.value)}
/>
This is a workaround for the bug that #cdoshi described.

Render fields for Redux Form from values in an array

I'm creating a filter for a graph which contains several fields. Most of them are known fields, but one part is dynamically and that is which of the houses the user want to be included in the graph. The houses are contained in my state and is different for each user (basically, the user chooses what they are named). It's the houses part here I want to render dynamically based on the props.
The only example of this that I've found is this, but I haven't found a solution on how I can transition that to my problem. I thought I could just do something like this where every house field is placed in a array (like in that example):
renderHouseFields() {
const { fields: { houseArray } } = this.props;
return this.props.houses.map((house) => {
const houseField = (
<label
{...houseArray}
className="col-xs-9 control-label"
htmlFor="cottageCheckbox"
>
<input type="checkbox" />
</label>
);
houseArray.addField(houseField);
return (
<div key={house.name}>
<label
className="col-xs-3 control-label"
htmlFor="cottage"
>
{house.name}
</label>
{houseField}
</div>
);
});
}
but then I simply get this error message:
Warning: setState(...): Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
This is my first project in React so I'm quite sure I'm just overlooking something here, but I can't find the solution and would be grateful if someone could help me here.
(I'm also aware that I can upgrade to redux form 6 and use FieldArray, but I don't really want to do that in the middle of the project.)
Judging by your code I reckon you're getting the error, because you are adding to your houseArray directly in the render method. This will trigger an update to the props of your component, which should not occur in the render method, hence the error.
If you look at the Deep Form link you supplied, you'll notice that the only place modifications to fields are occurring, is within button event handlers.
In your case I think what you want to do is link the entries in your house array, to the actual checkboxes. Right now you're only adding the checkboxes, but it has no reference to a house field:
<input type="checkbox" name={house} />
Or maybe this, depending on the properties of house:
<input type="checkbox" name={`${house}.id`} />
On a side note, I really would recommend to upgrade to version 6, since the API makes a lot more sense and it contains a lot of improvements over the previous version. There's a migration guide: http://redux-form.com/6.6.1/docs/MigrationGuide.md/

Resources