Access selected value from react's Select Component - reactjs

Hello dear community,
I want to create a very basic website for my school assignment.
I have a dropdown menu with a Select Component as its implementation. I need to access the selected value, which is a currency in my case, in order to update the information displayed on the page once a currency has been selected.
I am kind of frustrated since I wasn't able to find a helpfull solution to my relatively basic problem (I think it's basic :D)
My component class here:
import { Component } from "react";
import Select from 'react-select';
interface DropdownMenuProps {
values: [{}]
defaultValue: string
}
interface DropdownMenuState { }
/**
* Represents a Dropdown Menu
*/
export default class DropdownMenu extends Component<DropdownMenuProps, DropdownMenuState> {
render() {
return (
<div style={{ width: '120px' }}>
<Select id="dropdown-menu"
placeholder={this.props.defaultValue}
options={this.props.values}
// getOptionValue={(option) => option.value}
// getOptionLabel={(option) => option.label}
/>
</div>
)
}
}
This is how I create a dropdown menu compent:
<DropdownMenu defaultValue="Currency" values={[{ label: "EUR", value: "EUR" }, { label: "GBP", value: "GBP" }, { label: "USD", value: "USD" }]} ></DropdownMenu>
I'm glad for any tips :)

You have to use the onChange prop of react-select:
<select
id="dropdown-menu"
onChange={handleSelectChange}
>
and in this function you could handle the changes:
const handleSelectChange = (selectedVal) => console.log(selectedVal)

I recommend you using directly onChange and save it into a state:
1st:
Create state with the name you want:
const [selectValue, setSelectValue] = useState({});
2nd: Create options:
const options = [
{ label: "Tomate", value: 1 },
{ label: "Queso", value: 2 }
];
3rd: add method onChange in select and pass options:
const onChange = (ev) => {
setSelectValue(ev);
//console.log(ev);
console.log(selectValue);
};
<Select
id="dropdown-menu"
placeholder={"e"}
options={options}
onChange={onChange}
/>
I have created demo here:
https://codesandbox.io/s/ancient-pond-96h53?file=/src/App.js

Related

react typescript set default value multiselect

I am using this module
import { MultiSelect } from "react-multi-select-component"
and creating form by this
const [selected_to2, setSelected_to2] = useState([]);
<MultiSelect
options={options2}
value={selected_to}
onChange={setSelected_to}
labelledBy="Select2"
/>
then I creating multiselect component with default value using this
selected_to2.push({
value: item?.Code,
label: item?.Name
})
but returning value with 4 time called in the multiselect form, any proper way to set default value of multiselect then also add and remove in multiselect item?
React state must updated by set function. Edit the value directly will not work.
So you need do
setSelected_to2(s => [...s, {
value: item?.Code,
label: item?.Name
}])
First of all you are updating state is a wrong way
Wrong way
selected_to2.push({
value: item?.Code,
label: item?.Name
})
Right way:
setSelected_to2([{
value: item?.Code,
label: item?.Name
}
])
Here's a quick example that I did might help you, remember your default value must be an array of selected values since it's a multiselect component.
JSX
import { useState } from "react";
import { MultiSelect } from "react-multi-select-component";
import "./App.css";
const options = [
{ label: "The Godfather", value: 1 },
{ label: "Pulp Fiction", value: 2 },
];
const App = ({ editMode = true }) => {
const [value, setValue] = useState(editMode ? [options[1]] : []);
return (
<div className="App">
<MultiSelect
options={options}
value={value}
onChange={(selectedValues) => setValue(selectedValues)}
labelledBy="Select2"
/>
</div>
);
};
export default App;

Unable to maintain formik state values within react-select component

I am using react-select (multi-values) with Formik together with Material-UI Stepper (wizard) and have the values stored successfully within Formik's initialStates values but when I advance to the next screen, using conditional component rendering within my Stepper and then return back one screen where my react-select component resides, it no longer holds/shows the values that have already been selected within my react-select component even though the values are still in Formik's initialStates values.
My state is as follows which is storing my selectedOptions correctly:
import Select from 'react-select';
const myOptions= [
{ value: 'Food', label: 'Food' },
{ value: 'Being Fabulous', label: 'Being Fabulous' },
{ value: 'Unicorns', label: 'Unicorns' },
{ value: 'Kittens', label: 'Kittens' },
];
"props": {
"myGroups": [
{
"myGroupName": "",
"selectedOptions": [
{
"value": "Unicorns",
"label": "Unicorns"
},
{
"value": "Kittens",
"label": "Kittens"
}
]
}
]
}
Here is the code for the react-select component:
<Formik initialValues={initialFormValues} validationSchema={formSchema} onSubmit={this.handleFormSubmit} enableReinitialize>
{({ handleSubmit, handleChange }) => (
<Form noValidate onSubmit={handleSubmit} autoComplete='off'>
<Select
options={myOptions}
isMulti={true}
name={`myGroups.${index}.selectedOptions`}
onChange={(selectedOption) => {
let e = { target: { name: `myGroups.${index}.selectedOptions`, value: selectedOption } };
handleChange(e);
}}
/>
</Form>
)}
</Formik>
When returning, I expected to see both "Unicorns" and "Kittens" within the select but it's empty.
Any ideas how I can maintain state within this component? Can I perhaps somehow use `defaultValue' ?
The only solution I found is to install this library : formik-material-ui
You can after easy import:
import { Select } from 'formik-material-ui';
And use it in the Field component props.

How can I set null as default value in Slider from Material UI

I'm checking the documentation and looks like Slider requires the values to be an integer and also fallback to the first or the last item in case I pass a number that is not in the list of values for the Slider.
I'm creating a component that asks the user to select one of these:
Never | Rarely | Sometimes | Frequently | Almost always | Always
But it doesn't make sense to me to have an initial one selected. The options should show up initially as none of them selected. Is this something that Slider was not created to do? Looks so simple not having a value as default. Am I missing something?
Material UI Slider docs: https://material-ui.com/api/slider/
Currently, it is not possible to have MuiSlider without value. It will pick value from defaultValue or value.
For your use case, in case you need to use Slider component, you need to introduce one more extra value (only for UI sake)
import { Typography, Slider } from "#material-ui/core";
const marks = [
{ label: "None", value: 0 },
{
label: "Never",
value: 1
},
{
label: "Rarely Sometimes",
value: 2
},
{
label: " Frequently",
value: 3
},
{
label: "Almost always",
value: 4
},
{
label: "Always",
value: 5
}
];
export default function DiscreteSlider() {
const [sliderValue, setSliderValue] = useState(marks[0].value);
const onSliderValueChange = (e, val) => {
setSliderValue(val);
};
return (
<div>
<Typography id="discrete-slider" gutterBottom>
Slider
</Typography>
<Slider
aria-labelledby="discrete-slider"
valueLabelDisplay="off"
value={sliderValue}
onChangeCommitted={onSliderValueChange}
marks={marks}
min={0}
max={5}
/>
</div>
);
}
Else you can also check for Rating component available in lab version and map its rating with your selection values.
import Rating from "#material-ui/lab/Rating";
import Typography from "#material-ui/core/Typography";
export default function SimpleRating() {
const [value, setValue] = React.useState(0);
return (
<div>
<Rating
name="simple-controlled"
value={value}
onChange={(event, newValue) => {
setValue(newValue);
}}
/>
</div>
);
}

How to format value of the React Select

I use "react final forms" and "react select".
I've organized an interface and functionality works, but I have one thing which I don't like.
React select requires options in next format:
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
and the value also should be set as { value: 'chocolate', label: 'Chocolate' }.
But for me is strange to have in my model of data (and send to the server also) the value like this - { value: 'chocolate', label: 'Chocolate' }, because I need only 'chocolate'.
Easy way is format the object into a single value after the form will be saved and format back from single value to the object before the rendering of the element. I know how to do it outside of form, but in this case I should solve this problem again and again for each select element separately.
What I would like to do:
Find a way how to set value of the react select as single value, like 'chocolate' instead of object.
OR
Create a wrapper for react select component and format value there when it sets (it's easy) and when the form get the value from this field (this I don't know how to do).
I will appreciate any help.
Method 1
With strings:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import Select from "react-select";
const data = ["1", "2"];
function SingleStringReactSelect() {
const [option, setOption] = useState();
return (
<section>
<Select
onChange={option => setOption(option)}
value={[option]}
getOptionLabel={label => label}
getOptionValue={value => value}
closeMenuOSelect={false}
options={data}
/>
</section>
);
}
Method 2:
Created example:
https://codesandbox.io/s/react-codesandboxer-example-z57ke
You can use map in options and with Wrapper like SingleValueReactSelect
import React, { Fragment, useState } from "react";
import Select from "react-select";
const data = ["chocolate", "strawberry", "vanilla"];
export function SingleValueReactSelect(props) {
const [selectedItem, setSelectedItem] = useState();
return (
<Select
{...props}
value={selectedItem}
onChange={item => {
setSelectedItem(item);
props.onChange(item.value);
}}
options={props.options.map(item => ({ label: item, value: item }))}
/>
);
}
export default function AppDemo() {
return (
<Fragment>
<p>SingleValueReactSelect Demo</p>
<SingleValueReactSelect
isClearable
isSearchable
options={data}
onChange={item => {
alert(item);
}}
/>
</Fragment>
);
}
You can transform/filter the object data once you are sending the form data to server or another component.
Setting the value of the react-select as a single value will not show it as selected in the React-Select.

How to disable `deselect-option` in `react-select`?

I would like to use the react-select multi Select component and be able to select the same option multiple times. However, react-select does not allow one to do this. You can change the dropdown to show already selected options with hideSelectOptions={false}, but if you select one of them again, it will be deselected.
This issue #3234 describes this same problem and sugggests that one way to solve this problem is to handle the action argument to onChange somehow.
Here is the solution that I attempted based off of the suggested solution:
import React, { Component } from "react";
import Select from "react-select";
export default class MultiSelect extends Component<*, State> {
handleChange(option, action) {
console.log(option, action);
// return;
if (action === "deselect-option") {
action = "select-option";
// now how do I do the component's state?
}
}
render() {
return (
<Select
isMulti
className="basic-single"
classNamePrefix="select"
name="color"
options={[{"label": "hello", "value": "hello"}, {"label": "world", "value": "world"}]}
hideSelectedOptions={false}
onChange={this.handleChange}
/>
);
}
}
I expected to be able to enter "hello" multiple times but when I tried to enter "hello" again it was deleted.
In options, the data field makes value dynamic with any key, in this case, use Date.now() to make dynamic. then use actions 'select-option' to append to options, use actions 'remove-value'' to filter all fields in the Options data field with a label matching with selected option label and append to data and append one more object to Options datafield
options = [
{ value: Date.now(), label: "SUBJECT" ,val:"SUBJ" },
{ value: Date.now, label: "VERB", val:"VERB" }
]
<Select options={options} isMulti onChange={(e, option) => {
if (option.action === "select-option") {
Options=[
...Options,
{
value: option.option.value + "_" + Date.now(),
label: option.option.label
}
];
} else if (option.action === "remove-value" ||option.action === "pop-value") {
tempData = data.filter(opt => opt.label !== option.removedValue.label)
Options=[
...tempData,
{
value: option.removedValue.value + "_" + Date.now(),
label: option.removedValue.label
}
]
}
}
} />

Resources