Unable to pass label in react-select dropdown - reactjs

I am not able to pass the label value in onChange event handler. Only the value is getting formed. I want to have access to the label. Do help with the same.
handleSelectChange function has access only to the value and not to the label or event of the select dropdown.
<Select name={this.props.name}
backspaceToRemoveMessage=""
closeOnSelect={!this.state.stayOpen}
searchable={false}
disabled={this.state.disabled}
multi
options={this.props.countries}
simpleValue={true}
value={this.state.value}
onChange ={this.handleSelectChange}
/>

It is because flag simpleValue=true parse handler parameter to string of values. Set this flag to false and your handleSelectChange will have access to array of selected objects. Than you have to generate your value manually. (e.g. value="one,two")
Example of value processing:
handleSelectChange = (val) => {
const value = val.map(item => item.value);
this.setState({
value
});
}

You can grab element that is selected in the example below in the updateState.
Example
import React from "react";
import Select from 'react-select';
export default class CoolExample extends React.Component {
constructor(props) {
super(props);
this.state = {value:"foo"};
}
updateState(element) {
this.setState({value: element});
}
render(){
var Select = require('react-select');
var options = [
{ value: 'foo', label: 'Foo' },
{ value: 'bar', label: 'Bar' }
];
return(
<Select
name="form-field-name"
value={this.state.value}
options={options}
onChange={this.updateState.bind(this)}
/>
);
}
}

Related

How to pre-select some values in react-select?

I am using react-select in a project. When a user clicks to update a post, I fetch the post's original data and fill the form. However I am not able to pre-fill the Select component.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
tags : [], // this contains the list of all the tags in system
incomingTags : [] // will contain the tags which are linked with the post
selectedTags : [] // contains the tags that have been selected by user
}
}
selectRef = null;
componentDidMount() {
fetch all the tags
this.setState({tags : fetchedTags});
fetch the post data
this.setState({incomingTags : fetchedPostTags});
}
handleTagInputChange = (selectedOptions) => {
this.setState({ selectedTags : selectedOptions });
}
render() {
return (
<CreatableSelect
ref={ref => {this.selectRef = ref;}}
isMulti
options={this.state.tags}
onChange={this.handleTagInputChange}
/>
)
}
}
Things I have tried -
Using defaultValue={this.state.defaultTags} but it does not change when the state is set.
Using value={this.state.defaultTags} but then I am not able to remove the selected tags or select any other tags. I went through a similar query - react-select: pre-select a value in multi-select dropdown
Using this.selectRef.selectOption() but it does not work for selecting multiple items
When you want to use controlled component, you have to set both value and onChange
import React, { Component } from 'react';
import CreatableSelect from 'react-select/creatable';
export default class CreatableSingle extends Component {
constructor(props) {
super(props);
this.state = {
tags : [],
}
}
handleChange = (
newValue
) => {
this.setState({ tags: newValue })
};
render() {
return (
<CreatableSelect
value={this.state.tags}
onChange={this.handleChange}
/>
);
}
}

Trouble updating radio button state value in parent component from child element

I'm currently working a a multipage checklist app to make a common checklist procedure more efficient.
my parent component called MainForm has all of the states for my app. In my first child element, I had to fill some text inputs. The states are updating and saving as planned. My second page (or other child element) was the portion where my checklist would begin. The issue is my app is rending, but the radiobutton value isn't being sent to my state. I'm also having an issue where I can select the 'yes' radio button and then the 'no' radio button, but I can't go from 'no' to 'yes'. radioGroup21 is the radio group that's giving me problem. All other states are working.
I'm getting an error in my console that says:
"Checkbox contains an input of type radio with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props.
I've tried removing the value tag and the defaultValue line in my Radio elements, but no luck. I've tried creating constructor(props) in my parent element but I still kept having issues."
So far I've tried removing the defaultValue in my radio button and after I tried removing the value line. Unfortunately I this did not help.
I also read about controlled and uncontrolled inputs. I've tried changing my parent components state to put them in a constructor(props) bracket. But no luck.
I also tried to not use the handleChange function and use the setState function with values of {radioButton21 === 'yes'} but that didn't work.
//Parent Component
Class MainForm extends Component {
state = {
step: 1,
projectNumber: '',
projectName: '',
numberOfSystems: '',
buildSheet: '',
controlPhilosophy: '',
projectLayoutDrawing: '',
projSoftwareValidation: '',
CppDrawing: '',
radioGroup21: '',
}
nextStep = () => {
const { step } = this.state
this.setState({
step : step + 1
})
}
prevStep = () => {
const { step } = this.state
this.setState({
step : step - 1
})
}
handleChange = input => event => {
this.setState({ [input] : event.target.value })
}
render(){
const {step} = this.state;
const { projectNumber, projectName, numberOfSystems, buildSheet , controlPhilosophy, projectLayoutDrawing, projSoftwareValidation, CppDrawing, radioGroup21 } = this.state;
const values = { projectNumber, projectName, numberOfSystems, buildSheet, controlPhilosophy, projectLayoutDrawing, projSoftwareValidation, CppDrawing, radioGroup21 };
switch(step) {
case 1:
return <ProjectInfo
nextStep={this.nextStep}
handleChange = {this.handleChange}
values={values}
/>
case 2:
return <PrelimInspection
nextStep={this.nextStep}
prevStep={this.prevStep}
handleChange = {this.handleChange}
values={values}
/>
export default MainForm;
-----------------------------------
//Child Component
import React, { Component } from 'react';
import { Form, Button, Radio } from 'semantic-ui-react';
import { throws } from 'assert';
class PrelimInspection extends Component{
saveAndContinue = (e) => {
e.preventDefault();
this.props.nextStep();
}
back = (e) => {
e.preventDefault();
this.props.prevStep();
}
render(){
const { values } = this.props
return(
<Form color='blue' >
<h1 className="ui centered">System Installation</h1>
<Form.Field inline>
<Form.Field>System Properly Supported</Form.Field>
<Radio
label = {'Yes'}
name = {'radio21'}
value = {'Yes'}
onChange={this.props.handleChange('radioGroup21')}
defaultValue={values.radioGroup21}
/>
<Radio
label = {'No'}
name = {'radio21'}
value = {'No'}
onChange={this.props.handleChange('radioGroup21')}
defaultValue={values.radioGroup21}
/>
</Form.Field>
<Button onClick={this.back}>Back</Button>
<Button onClick={this.saveAndContinue}>Save And Continue </Button>
</Form>
)
}
}
export default PrelimInspection
The app is rendering and the layout is correct. Unfortunately the state values aren't being sent to the parent state.
I checked the documentation https://react.semantic-ui.com/addons/radio/#types-radio-group and I have found few things you missed:
1.) Radio component asked the checked props (but you did not supply it).
2.) Which then requires you to pass the value, in your case it should come from the parent component:
<PrelimInspection
valueFromParent={this.state["radioGroup21"]}
nextStep={this.nextStep}
handleChange={this.handleChange}
values={values}
/>
so in your Child Component' render, take the value:
render() {
const { values, valueFromParent } = this.props;
...
3.) Radio's onChange value is passed as the second param (obj.value).
<Radio
label={'Yes'}
name={'radio21'}
value={"Yes"}
checked={valueFromParent === 'Yes'}
onChange={this.props.handleChange("radioGroup21")}
...
/>
So you can take the selected value like this:
// MainForm
handleChange = input => (event, obj) => { // obj is the second param
console.log("sendin here", input, obj.value);
this.setState({ [input]: obj.value });
};

REACT-SELECT: Is there a way to declare 'selected' in options?

Is there a way to declare 'selected' in options array,
and this 'selected' item will be displayed by default?
<Select onChange={this.changeUser}
options={[{value:1,labe:1},
{value:2,label:2,selected},
{value:3,label:3}]}
/>
As stated in the docs you can set a default selected value as value in state which you can update when the user switches to an alternate option using the onChange handler
Take a look at this example from the docs
import React from 'react';
import Select from 'react-select';
class App extends React.Component {
state = {
selectedOption: {value: 'one', label: 'One'},
}
handleChange = (selectedOption) => {
this.setState({ selectedOption }); // this will update the state of selected therefore updating value in react-select
console.log(`Selected: ${selectedOption.label}`);
}
render() {
const { selectedOption } = this.state;
const value = selectedOption && selectedOption.value; // this will read from state and set the value in state as the selected value. Therefore setting a value even when none has yet to be selected.
return (
<Select
name="form-field-name"
value={value} // so here the default value of one will be set then updates during the on change event
onChange={this.handleChange}
options={[
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' },
]}
/>
);
}
}
Set a selected value in the state the set the value of this option as the value in react-select

Can't get attributes of material-ui SelectField in react

I'm using SelectField of material-ui for my react project.
I have tried many ways from this answer Can't get the target attributes of material-ui select react component
.
But they don't work.My target.id always equals ""
How can I get the attributes (like id).
Here is my code:
constructor(props) {
super(props);
this.state = {
form: {
resident_city: ''
},
ret_code: '',
ret_msg: ''
};
this.handleList = this.handleList.bind(this);
}
handleList(event, index, value) {
event.persist()
const field = event.target.id;
const form = this.state.form;
form[field] = value;
console.log(event, value)
this.setState({
form
});
console.log(form);
}
<form>
<SelectField
style={style}
id="city"
value={this.state.form.resident_city}
onChange={this.handleList}
maxHeight={200}
>
{cities}
</SelectField>
</form>
Update
I tried to use SelectField without form,and I still can't get the id attributes.It is really confusing me.
On the main component you define a prop name for select the form component let say your city component is called : cityForm
in your cityForm component
render() {
return (
<SelectField
style={style}
value={this.props.city}
onChange={(e, index, value) => this.props.selectChange(e, index, value, this.props.cityName)}
maxHeight={200}
>
{cities}
</SelectField>
);
}
}
In your main comp you will have let say (code is cutted some part omitted)
handleSelectChange(e, index, value, name){
this.setState({
[name] : value,
});
}
render(){
return (
<cityForm cityName = "city1" city={this.state.city1} selectChange={this.handleSelectChange}/>
);
}
}
Im building a dynamic form generator and it did the trick for me =).
If a React class component is used, selected value can be accessed through its state object.
Alternatively, with help of Redux the Select's onChange method can dispatch an action and update the value in the main application state.
In cases when updating the main state isn't feasible and function component is chosen instead of a class component, getting the value from the component outside the function becomes cumbersome.
An easy way to fix it would be to add a hidden input referencing the same value as select uses. Consider the following piece of code. It uses Selector field1 to update value through internal component state and binds it to the hidden field theField. The value can be further read an outside function during dispatch just like any other input field value in the form.
import React, { useState } from 'react';
import { Button, FormControl, MenuItem, Select } from '#material-ui/core';
import { connect } from 'react-redux';
const mapStateToProps = () => ({
});
const mapDispatchToProps = (dispatch, ownProps) => ({
submitForm: (event) => {
event.preventDefault();
console.log(event.target.theField.value);
dispatch({
type: 'UPDATE_THE_FIELD',
theField: event.target.theField.value,
});
}
});
function Main(props) {
const [field1, setField1] = useState("v1");
return (
<>
<form onSubmit={(event) => { props.submitForm(event, props) }}>
<FormControl>
<Select
value={field1}
onChange={(event) => setField1(event.target.value)}
>
<MenuItem value="v1">V1</MenuItem>
<MenuItem value="v2">V2</MenuItem>
</Select>
</FormControl>
<Button type="submit">Update</Button>
<input type="hidden" name="theField" value={field1} />
</form>
</>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Main);

React prop only changes state after selecting twice

I am using React Select and for some reason my state is only changing after an option has been selected twice.
I have the following code:
var React = require('react');
import Select from 'react-select';
class VehicleSelect extends React.Component {
constructor(props) {
super(props);
this.state = { brandSelect: ""};
}
_onChange(value) {
//console.log(value) - just to see what we recive from <Select />
this.setState({brandSelect: value});
console.log(this.state.brandSelect);
}
render() {
var options = [
{ value: 'Volkswagen', label: 'Volkswagen' },
{ value: 'SEAT', label: 'SEAT' },
{ value: 'SKODA', label: 'SKODA' }
];
return (
<Select
name="form-field-name"
value={this.state.brandSelect}
options={options}
placeholder="Select a brand"
searchable={false}
onChange={this._onChange.bind(this)}
/>
)
}
};
// Export our component
export default VehicleSelect;
When one of the options is selected it won't console.log the new state however if I select the option again it will. Any idea where I am going wrong, I'm guessing because the state isn't being shown in the console.log it isn't updating?
Thanks
setState does not change state immediately. You need to use a callback. Docs.
_onChange(value) {
//console.log(value) - just to see what we recive from <Select />
this.setState({brandSelect: value}, () => {
console.log(this.state.brandSelect);
});
}

Resources