React-select does not show the selected value in the field - javascript

i have a react-select component which i define like this:
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value)}
placeholder="Select Portfolio"
/>
with opts = [{label: any, value:1}, {label:Two, value:2}].
The values when selected are stored in the state via portfolioSelector function. The problem is that when i select a value it wasn't show in the select field. My main component is this:
const PortfolioSelector = ({
opts,
portfolioSelector
}) => {
if (opts) {
return (
<div className="portfolio select-box">
<label htmlFor="selectBox" className="select-box__label">
Portfolio
</label>
<div className="select-box__container">
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value)}
placeholder="Select Portfolio"
/>
</div>
<div className="separator" />
</div>
);
}
return (
<div>Loading</div>
);
};
Do you know why?

This is an alternative solution that i used.
Demo: https://codesandbox.io/s/github/mkaya95/React-Select_Set_Value_Example
import React, { useState } from "react";
import Select from "react-select";
export default function App() {
const [selectedOption, setSelectedOption] = useState("none");
const options = [
{ value: "none", label: "Empty" },
{ value: "left", label: "Open Left" },
{ value: "right", label: "Open Right" },
{
value: "tilt,left",
label: "Tilf and Open Left"
},
{
value: "tilt,right",
label: "Tilf and Open Right"
}
];
const handleTypeSelect = e => {
setSelectedOption(e.value);
};
return (
<div>
<Select
options={options}
onChange={handleTypeSelect}
value={options.filter(function(option) {
return option.value === selectedOption;
})}
label="Single select"
/>
</div>
);
}

<Select
options={this.props.locale}
onChange={this.selectCountryCode}
value={{label : this.state.selectedCountryLabel}}
/>
The value property expects the shape Array.

The value is handled really bad, and it needs hacks like here, explained here.
Long story short; the value works differently. You'd expect
value={MY_VALUE}, but it works instead
value={{label: MY_VALUE}}.

First thing is you are created the wrong array, if label: any or Two is string you have to add double quote.
Look at this:
opts = [{label: "any", value:1}, {label:"Two", value:2}]
Second, You must remember the options in this case is opts is an array of object which have label and value, what the data you want to add to your state?
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value.value /* or if you want to add label*/ value.label)}
placeholder="Select Portfolio"
/>

You can simply put the value property as Selected.label
value={selectedOption.label}

I fixed it.
You forgot add value property. Use this, check the working code:
const opts = [{ label: 'any', value: 1 }, { label: 'Two', value: 2 }];
const PortfolioSelector = ({ options }) => {
if (options) {
return (
<div className="portfolio select-box">
<label htmlFor="selectBox" className="select-box__label">
Portfolio
</label>
<div className="select-box__container">
<Select
id="portf"
options={options}
value={this.state.opts1}
onChange={value => this.setState({ opts1: value })}
placeholder="Select Portfolio" />
</div>
<div className="separator" />
</div>
);
}
return <div>Loading</div>;
};
and call your component
<PortfolioSelector options={opts} />

For any one who is facing problems with React-Select getting populated or React-select doesn't get selected value; try to give it a dynamic key attribute who changes every time your data changes (either options array or selected option), so it will re-render with new data.

this is my solution
Demo: https://codesandbox.io/s/prod-rgb-o5svh?file=/src/App.js
code:
import axios from 'axios'
import {useEffect, useState} from 'react'
import Select from 'react-select'
import "./styles.css";
export default function App() {
const [users, setUsers] = useState()
const [userId, setUserId] = useState()
useEffect(()=>{
const getUsers = async () => {
const {data} = await axios.get('https://jsonplaceholder.typicode.com/users')
setUsers(data)
}
getUsers()
},[])
const options = users && users.map(user =>{
return {label: user.name, value: user.id}
})
console.log(userId)
return (
<div className="App">
{users && (
<Select
placeholder='Select user...'
isSearchable
value={options.label}
options={options}
onChange={(option) => setUserId(option.value) }
/>
)}
</div>
)
}

Please provide lable and value object together like {label: ?, value: ?}
const selectedValue = options.find(x => x.value===value);
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value)}
placeholder="Select Portfolio"
value={label : selectedValue.label, value: (value ? selectedValue.value : "")}
/>

opts = [{label: any, value:1}, {label:Two, value:2}]
value must be string.

Related

not work `onChange` and not work `setState` in `select` tag. (multiple) in react

I have a select tag containing the optgroup and option tags which is multiple.
When I select the items, the state is not updated and the onChange does not work.
I want the value of the option tag to be transferred to state when the item or items are selected !!!.
const FunctionalComponent = () => {
const [mystate , setMyState] = useState([]);
return(
<div>
<select
onChange={(e) => setMyState(e.target.value) }
className='form-control'
multiple='multiple'
value={mystate}
>
{datas.map((obj) => (
return (
<optgroup key={obj.title} label={obj.title}>
{obj.map((o) => (
<option key={o.id} value={o.id}>{o.name}</option>
))}
</optgroup>
);
))}
</select>
</div>
)
}
export default FunctionalComponent
Thanks to those who help me.
Without knowing how datas is structured it's difficult to write code for it, but based on how I think it's structured here some working code.
Intialiase state as an array.
Have your handler get the selectedOptions, and get each option's value. Add that array to your state.
Here datas is an array objects. Each one has a title, and another array of objects containing the option data. map over the main array, and then map over the options array.
const { useState } = React;
function Example({ datas }) {
const [mystate , setMyState] = useState([]);
function handleChange(e) {
const options = e.target.selectedOptions;
const values = Array.from(options, option => option.value);
setMyState(values);
}
return (
<div>
<select
onChange={handleChange}
className="form-control"
multiple="multiple"
value={mystate}
>{datas.map(obj => {
return (
<optgroup
key={obj.title}
label={obj.title}
>{obj.options.map(obj => {
return (
<option
key={obj.id}
value={obj.id}
>{obj.name}
</option>
);
})}
</optgroup>
);
})}
</select>
</div>
);
}
const datas = [
{
title: 1,
options: [
{ id: 1.1, name: 1.1 },
{ id: 1.2, name: 1.2 },
]
},
{
title: 2,
options: [
{ id: 2.1, name: 2.1 },
{ id: 2.2, name: 2.2 },
]
},
];
ReactDOM.render(
<Example datas={datas} />,
document.getElementById('react')
);
form-control { width: 200px; height: 200px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How to add required to react-select?

I'm using react-select library to add dropdown menu for my app, but "required" doesn't work (I read a discussion on GitHub for this library, creators haven't added that function yet), so for now how do I make select required? (I read here another post with the same problem, solution presented there didn't work for me). My code is:
import React, { useState } from "react";
import Select from "react-select";
export default function App() {
const [data, setData] = useState();
const options = [
{ value: "1", label: "1" },
{ value: "2", label: "2" },
{ value: "3", label: "3" },
{ value: "4", label: "4" }
];
const handleSubmit = (e) => {
console.log(data);
};
return (
<div className="App">
<form onSubmit={handleSubmit}>
<input required placeholder="name" />
<Select
options={options}
onChange={(e) => setData(e.value)}
value={options.filter(function (option) {
return option.value === data;
})}
label="Single select"
placeholder={"Select "}
menuPlacement="top"
required
/>
<button> Submit</button>
</form>
</div>
);
}
code sandbox
In my code I have a couple of regular inputs (where required works fine) but I want the Select also be required. Any suggestions are greatly appreciated.
I would think outside the box — in this case the Select component. What can you add that gets the same result? I took a quick stab at this for you:
const [isValid, setIsValid] = useState(false);
// This effect runs when 'data' changes
useEffect(() => {
// If there is data, the form is valid
setIsValid(data ? true : false);
}, [data]);
...
return (
<div>
<Select ... />
{!isValid && <p>You must choose a value</p>}
<button disabled={!isValid}>Submit</button>
</div>
)
https://codesandbox.io/s/vigilant-wiles-6lx5f
In this example, we check the state of the Select component — if it's empty (the user hasn't chosen anything) the form is invalid and the submit button is disabled.

set boolean value on JSON object with react hooks

Im trying to set a boolean value on an object to submit them all together, all the values comes from a form and most from text inputs, all text inputs are setting correctly except for my boolean element, Im not understanding exactly what Im doing wrong so any help is very appreciated. Heres my code:
import React, {useState} from 'react';
import {Col} from "react-bootstrap";
import EditorElement from "../components/editorElement";
import BootstrapSwitchButton from "bootstrap-switch-button-react";
export default function ListDetails({listdetails, updateData, updatingData, selectedRow}) {
const [input, setInput, bool] = useState(
{
enabled: listdetails.enabled, // <-- Here I set (or want to set) the value of my boolean, the "listdetails" parameter are the default values that comes from initial fetch.
name: listdetails.name,
custom1: listdetails.custom1,
id: selectedRow
}
);
const updateInputs = event => setInput({...input, [event.target.name]: event.target.value});
const updateInputsBoolean = event => setInput({...input, [event.target.name]: event.target.checked}); //<-- Here I updatethe value of my bool element
const{enabled, name, hooktype, custom1, custom2, custom3, custom4, custom5, endpoint} = input; // <-- Here I update all the values
const handelSubmit = evt => {
console.log(input);
updateData(input, bool); //<-- Here I set the collected object and set it but "bool" is not setting
};
function handleBoolean(ev) { // <-- If I run this function in the boolean onChange I get the true or false value on console but I couldnt set it in the updateData (that comes from another component where I have the axios post)
const setBool = ev.toString();
console.log(setBool);
// updateData(setBool);
}
return (
<div>
<Col className={'col-md-6'}>
<EditorElement name='Enable/ Disabled '>
<div>
<BootstrapSwitchButton
checked={enabled === true}
onstyle="primary"
offstyle="danger"
name={'enabled'}
value={enabled}
onChange={e => updateInputsBoolean(e)} // <-- Here is my boolean element that is a bootstrap switch
/>
</div>
{listdetails.enabled ? 'is enabled' : 'is not enabled'}
</EditorElement>
<EditorElement name='Name'>
<input
type={'text'}
defaultValue={name}
name={'name'}
className={'form-control'}
onChange={e => updateInputs(e)}
/>
</EditorElement>
</Col>
<Col className={'col-md-6'}>
<EditorElement name='Custom1'>
<input
type={'text'}
name={'custom1'}
defaultValue={custom1}
className={'form-control'}
onChange={e => updateInputs(e)}
/>
</EditorElement>
</Col>
<Col style={{'marginBottom': '30px', 'marginTop': '20px'}} className={'col-md-12 text-right'}>
<button
style={{'marginTop': '15px', 'marginBottom': '15px'}}
type={'button'}
className={'btn btn-primary'}
onClick={handelSubmit} //<-- Here I handle my submit
>
{updatingData ? 'Updating...' : 'Save'}
</button>
</Col>
</div>
);
}
Thanks in advance for any help!
#DrewReese helped me understand this, I was confusing BootstrapSwitchButton as a normal input and it is not like that. Here is the working code now:
const [input, setInput] = useState(
{
enabled: listdetails.enabled,
name: listdetails.name,
custom1: listdetails.custom1,
id: selectedRow
}
);
const updateInputs = event => setInput({...input, [event.target.name]: event.target.value});
const{enabled, name, custom1} = input;
const handelSubmit = evt => {
console.log(input);
updateData(input);
};
function handleBoolean(ev) {
const setBool = ev.toString();
console.log(setBool);
setInput({...input, enabled: ev}); //<-- I wasn't updating the enabled prop event here and now I make a copy of all inputs and set the event of enabled... VOILA! is working :)
}
Thanks agan #DrewReese for helping me understand that

How to sync two dropdown lists with different display in React?

I have a list of countries, with key, value, text.
I would like to have two Dropdown (https://react.semantic-ui.com/modules/dropdown/) list, one shows the key, the other the text.
The goal is to allow to choose by key of by text (we can type in the dropdown); if I update one, the other is synchronized immediately.
How can I achieve this ?
<Dropdown
id='form-input-country'
label='Country'
placeholder='Select Country'
fluid
search
selection
options={countryISOOptions} // will show text
/>
<Dropdown
id='form-input-country'
label='Country'
placeholder='Select Country'
fluid
search
selection
options={countryISOOptions} // want to show key + want to sync in both direction
/>
I import countryISOOptions which looks like:
export const countryISOOptions = [
{key: 'AF', value: '4', text: 'Afghanistan'},
{key: 'AL', value: '8', text: 'Albania'},
{key: 'DZ', value: '12', text: 'Algeria'},
...
Maintain 2 option arrays. One for text and other for keys(derived from the first options array). Then maintain just one state and an onChange for both dropdowns and you will be fine.
See working copy of your code.
See code snippet:
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
import "./styles.css";
const countryISOOptions = [
{ key: "AF", value: "4", text: "Afghanistan" },
{ key: "AL", value: "8", text: "Albania" },
{ key: "DZ", value: "12", text: "Algeria" }
];
const countryKeys = countryISOOptions.map(({ key, value }) => ({
value,
text: key
}));
export default function App() {
const [text, setText] = useState("");
const onChangeTextDropdown = (e, d) => {
console.log("onChangeTextDropdown", e.target.value);
console.log("d", d);
setText(d.value);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Dropdown
id="form-input-countryz"
label="Country"
placeholder="Select Country - text"
value={text}
onChange={onChangeTextDropdown}
fluid
search
selection
options={countryISOOptions} // will show text
/>
<Dropdown
id="form-input-country"
label="Country"
placeholder="Select Country - key"
value={text}
onChange={onChangeTextDropdown}
fluid
search
selection
options={countryKeys} // want to show key + want to sync in both direction
/>
</div>
);
}
If you are using controlled version, then each Dropdown is a typical Inputthat supports two props called value and onChange. I'll use hook in the following example,
const [value1, setValue1] = setState('')
const [value2, setValue2] = setState('')
const onValue1Change = e => {
const value = e.target.value
setValue1(value)
if (value === 'key') setValue2('country')
}
return (
<div>
<Dropdown
value={value1}
onChange={onValue1Change}
...
/>
<Dropdown
value={value2}
...
/>
</div>
)

set maximum character input size of react CreatableSelect

I am using creatable select to allow the user to input a new option that is not in the dropdown list. But after looking I cannot seem to see a way of setting the maximum input to 50 characters for input before creating in the creatable select.
I have looked at taking the new entry and if over 50 characters deleting it however this seems a long way round and would like to use something that is shorter on the actual input when the user selects create.
import CreatableSelect from 'react-select/creatable';
const cars = [
{ label: "audi", value: 1 },
{ label: "bmw", value: 2 },
{ label: "ford", value: 3 },
{ label: "VW", value: 4 },
];
const selectOption = () => (
<div className="app">
<div className="container">
<CreatableSelect
options={cars}
placeholder={"check and enter new car name here"}
isClearable
onChange={(opt, meta) => console.log(opt, meta)}
/>
</div>
</div>
);
export default selectOption
I am hoping there is a max input option i just dont know. Thank you for taking the time to look at this/help, very much appreciated.
Simply put you can use the <CreatableSelect/> s onCreateOption prop. You will have to maintain your options and value in component state. Then put your control logic inside handleCreateOption function ( for onCreateOption prop ). Your handleCreateOption will be something like this. ( look at codesandbox for full code )
handleCreateOption = inputValues => {
if (inputValue.length < 50) {
const newOption = createOption(inputValue);
this.setState({
options: [...options, newOption],
value: newOption
});
}
}
codesandbox : https://codesandbox.io/embed/react-codesandboxer-example-cjbgu
If you don't want the user to be able to type more than the limit, you can add maxLength attribute to the input.
import React, { useEffect, useRef } from 'react';
const myRef = useRef(null);
useEffect(() => {
myRef.current.inputRef.style.minWidth = 'max-content';
myRef.current.inputRef.placeholder = placeholderText;
myRef.current.inputRef.maxLength = 20;
}, []);
<CreatableSelect
ref={myRef}
{...props}
options={options}
value={value}
name={name}
onChange={handleChange}
placeholder={''}
classNamePrefix="multi-select-custom"
isMulti={isMulti}
/>

Categories

Resources