Input Value doesn't change when selecting an option in react-select - javascript

I'm using react-select to define a select input control in my react application. This is how I'm using the component:
<Select
onChange={function(e) {console.log(e)}}
options={[
{value: "sf", label: "San Francisco"},
{value: "nyc", label: "New York City"}
]}
></Select>
Before selecting any option I see a Select... placeholder as the input value. This doesn't change after selecting an option: the input value doesn't change and the Select... placeholder appears to be the selected "option".
Is there something wrong with how I'm using the component?

Define the Select value in state variable, and logChange function will return an object, assign the value of that object to state variable, it will work, Check this code:
class App extends React.Component{
constructor(){
super();
this.state = {value: ''}
}
logChange(val) {
console.log("Selected: " + val.value);
this.setState({value: val.value});
}
render(){
var options = [
{value: 'one', label: 'One' },
{value: 'two', label: 'Two' }
];
return(
<Select
name="form-field-name"
value={this.state.value}
options={options}
onChange={this.logChange.bind(this)}
/>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/classnames/index.js"></script>
<script src="https://unpkg.com/react-input-autosize/dist/react-input-autosize.js"></script>
<script src="https://unpkg.com/react-select/dist/react-select.js"></script>
<link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css">
<div id='app'/>

Related

How to use JS Fiddle for rending React select

I want to render third party library react-select in JS Fiddle. I have added libraries in jsfiddle but not sure how to use Select component from react-select. I am getting "Error Select is not defined".
https://jsfiddle.net/7nydx09p/1/
const App = () => {
return <div> Test
<Select />
</div>
}
ReactDOM.render(<App/>, document.getElementById('root'));
look here : https://jsfiddle.net/zh4593oL/1/
look here for the issue : https://github.com/JedWatson/react-select/issues/4120
html
<div id="root"></div>
<script type="module">
import Select from 'https://cdn.pika.dev/react-select#^3.1.0';
window.Select = Select;
</script>
js
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
const App = () => {
return <div> <Select options={options} /> </div>
}
ReactDOM.render(<App/>, document.getElementById('root'));

react-select-multi selection ,select props value

this is my muti selection component
import React from 'react';
import MultiSelect from "#khanacademy/react-multi-select";
const options = [
{label: "One", value: 1},
{label: "Two", value: 2},
{label: "Three", value: 3},
];
class Consumer extends React.Component {
state = {
selected: [],
}
render() {
const {selected} = this.state;
return <MultiSelect
options={options}
selected={selected}
onSelectedChanged={selected => this.setState({selected})}
/>
}
}
when i click the value, it will be selected in post component, In my view component, I want to show ,how may option I selected using multi selection plugins
<Select
isMulti
/>
this isMulti will handle multi-select
the Select component takes several params. You can make it Creatable and as well as Searchable. you can refer here https://github.com/JedWatson/react-select

Is there any way I can use isMulti without it deleting choices I've already picked? In otherwords, having duplicate/repeated selected options?

Basically, I want to use the react-select library and use the isMulti prop, but the problem with that after selecting an option, the value would be deleted. As you can see below with the provided images, as soon as I click "US: 1" that option would go away. But for the app I'm trying to build, it's certainly possible for a customer to want 2 of the same sizes. Therefore they would pick 2 "US: 1" and it automatically sets the quantity to 2. The problem is that as soon as they pick "US: 1" that option goes away.
This is all I currently have now.
const options = [
{value: 1, label: "US: 1"},
{value: 1.25, label: "US: 1.25"},
{value: 1.5, label: "US: 1.5"},
{value: 1.75, label: "US: 1.75"},
{value: 2, label: "US: 2"},
{value: 2.25, label: "US: 2.25"},
]
class Details extends Component {
state={
selectedOption: []
}
handleChange = (selectedOption) => {
this.setState({ selectedOption: selectedOption });
}
render() {
<Select isMulti={true} isSearchable={true} onClick={value.changeSize(id, selectedOption)} value={selectedOption} onChange={this.handleChange} options={options}></Select>
}
}
Here's an example of what I'm talking about. "US: 1" goes away when it's clicked when I want that option to stay. I'm thinking it alters my "options" array and displaying the new one that doesn't have the clicked option. If I can somehow keep feeding it these original values after every single on onChange that would be awesome. I'm not sure how to dig into the library on how to do it or if it's even possible.
https://www.npmjs.com/package/react-select
Here how I would do it:
class Details extends Component {
state = {
selectedOption: []
};
handleChange = selectedOption => {
const newSelectedOption = selectedOption.map(opt => ({
label: opt.label,
innerValue: opt.value,
// I set a random value because it is needed to be able to delete the value without deleting all of them
value: Math.random()
}));
this.setState({ selectedOption: newSelectedOption });
};
render() {
return (
<Select
isMulti={true}
isSearchable={true}
value={this.state.selectedOption}
onChange={this.handleChange}
options={options}
/>
);
}
}
The idea is not to use value as it's original goal. When a label props is passed to value inside Select it still displays it correctly. So you will base yourself on innerValue and trick react-select.
Here a live example
I guess all you need is to add hideSelectedOptions={false} to <Select />.
Like:
<Select
isMulti={true}
hideSelectedOptions={false}
options={options}
...
/>

React JS props updated, but not rendered

The essence of this program is that when you enter any value into an input, you get 2 random numbers and 2 random strings. Since the onChange event is worthwhile during the input of the number, it must be changed and rendered. But the numbers do not appear. However, using React Developer Tools, I see that the values are generated.
All code:
<html>
<head>
<meta charset="utf-8" />
<title>Page Title</title>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class TextInput extends React.Component {
constructor(props) {
super(props);
this.state = {dropDownList: null};
this.eachRender = this.eachRender.bind(this);
}
eachRender() {
this.eachNumbers = [Math.random(0,10), Math.random(0,10)]; //Numbers are generated randomly
this.eachString = ["One random string", "Another random string"]; //Strings are also generated randomly, in order to simplify the code, they were given static values
var text = document.getElementById("text").value;
if (text !== ""){
this.setState({dropDownList: <DropDownList numbers = {this.eachNumbers} someString = {this.eachString}/>});
}
else this.setState({dropDownList: null});
}
render() {
return ( <div>
<input type="text" id="text" onChange={this.eachRender}>
</input>
{this.state.dropDownList}
</div> )
}
}
class DropDownList extends React.Component {
constructor(props) {
super(props);
this.eachTask = this.eachTask.bind(this);
this.state = { items: [ //The data should be presented as follows
{id: 1, item: this.props.numbers[0], href: this.props.someString[0]},
{id: 2, item: this.props.numbers[1], href: this.props.someString[1]},
] };
}
eachTask(items) {
return(
<li key = {items.id}>
Rund Number: <b>{items.item.toFixed(3)}</b> <br></br>
Rund String <b>{items.href}</b>
</li>
)
}
render() {
return(
<ul>
{this.state.items.map(this.eachTask)}
</ul>
)
}
}
ReactDOM.render(
<TextInput />, document.getElementById("app")
)
</script>
<script crossorigin src="https://unpkg.com/react#16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.25.0/babel.min.js"></script>
</body>
</html>
I think the problem revolves around this line of code:
this.state = { items: [
{id: 1, item: this.props.numbers[0], href: this.props.someString[0]},
{id: 2, item: this.props.numbers[1], href: this.props.someString[1]},
] };
How can this be fixed?
Use setState if you want to change the value of this.state.
Per React docs:
Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.
Sorry for my poor english;
In DropDownList: render props directly instead of state;
It does seems to create a brand new DropDownList in method eachRender, but the only difference is props, you can print it in console.
welcome suggestion:)

React - how to pass multiple input values to child in on change event when values have different types (is not always e.target.value)?

I have multiple input fields and 1 react-select dropdown field. I created a method in my parent component that sets the state with the values from the input, passes it down to the child which should call the method. My problem is that react-select doesn't take the value but an object like this:
{value: 'xy', name:'x', label: 'y'}
so normally my function in my onChange event handler would look like this (when passing multiple values):
in parent:
testing(e) {
this.setState({
[e.target.name]: e.target.value
})
}
in child:
<input type="text" name="maxfare" onChange={this.onChange}/>
...
onChange(e){
var value = [e.target.name] = e.target.value;
this.props.onChange(value);
}
...
However, while my input fields take:
e.target.value
my select dropdown takes entire 'e' - not e.target.value. I tried to pass my onChange function in child component 2 arguments, calling my method in parent with 2, but that doesn't to work. Any help would be great! My code is below (the relevant parts- if I forgot something that you think is important, please let me know). Ps. I thought about having 2 onChange functions, passing once my value for select dropdown and a second one doing the rest, but then I would need to pass 2 onChange methods to the child and I believe thats not possible in react?! Thanks!!:
Parent:
...
onChangeT(selectValue, value) {
this.setState({
origin: selectValue,
maxfare: value
...
})
}
render(){
....
<Parent cities={this.state.citiesToSelect} origin={this.state.origin} maxfare={this.state.maxfare} onChange={this.onChangeT}/>
...
}
Child:
....
onChangeC(e){
var value = [e.target.name] = e.target.value;
this.props.onChange(e, value);
console.log("name", name)
}
....
<Select
onChange={this.onChangeC}
labelKey='name'
value={this.props.origin}
options={this.props.cities}
/>
<input type="text" name="maxfare" onChange={this.onChangeC}/>
We want to be able to do this in the parent
onChange = (name, value) => {
this.setState({[name]: value});
}
We fix the "wiring" of the children onChange to do exactly that, raise an onChange with a name and a value. Wrap react-select and provide a consistent interface to the parent.
Form example
import * as React from 'react';
import Input from './Input';
import Select from './Select';
export default class Form extends React.Component {
state = {
input: '',
select: '',
options: ['A', 'B', 'C']
};
onChange = (name: string, value: string) => {
this.setState({[name]: value});
}
render() {
return (
<form>
<Input
label="Surname"
name={'input'}
value={this.state.input}
onChange={this.onChange}
/>
<Select
label="Grade"
name={'select'}
value={this.state.select}
options={this.state.options}
onChange={this.onChange}
/>
</form>
);
}
}
Input example
import * as React from 'react';
export default class Input extends React.Component {
onChange = (e) => {
const {onChange, name} = this.props;
if (onChange) {
onChange(name, e.currentTarget.value);
}
}
render() {
return (
<div>
<label>{this.props.label}</label>
<input
type="text"
name={this.props.name}
value={this.props.value}
onChange={this.onChange}
/>
</div>
);
}
}
And a DOM native <Select /> example
import * as React from 'react';
export default class Select extends React.Component {
onChange = (e) => {
const {onChange, name} = this.props;
if (onChange) {
onChange(name, e.currentTarget.value);
}
}
render() {
return (
<div>
<label>{this.props.label}</label>
<select
name={this.props.name}
value={this.props.value}
onChange={this.onChange}
>
{this.props.options.map(o => <option key={o}>{o}</option>)}
</select>
</div>
);
}
}
The fact that react-select doesn't return a native event nor a similar object shape of a native event, is forcing you to normalize the shape of the object that returned from it. You can do that by wrapping the Select component of react-select with your own component and returning a custom object for your use-case.
In this example we are trying to normalize the behavior of our onChange event both for inputs and Select. We will first check if the object that returned is having a target key, if it does we know that this is a native event that we are handling and we will set the state according to the name of the input and its value (exactly how you did it in your example).
If we don't have a target key, then we may handle a different kind of event.
We will check if we get a selectedValue key (just a convention between yourself, you can change the key as you like), then we will set the state by its name and selectedValue that we received.
This will only work if you will pass the name upwards of course.
So the object that you need to return from the custom Select component should look something like this:
{name: this.props.name, selectedValue }
// where selectedValue is the object received from the real Select component
Here is a running example:
const options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' },
]
const moreOptions = [
{ value: 'mike', label: 'johnson' },
{ value: 'lynda', label: 'bog' },
]
class MySelect extends React.Component {
handleChange = selectedValue => {
const { name, onChange } = this.props;
onChange({ name, selectedValue });
}
render() {
const { options, value, ...rest } = this.props;
return (
<Select
{...rest}
value={value}
onChange={this.handleChange}
options={options}
/>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
option1: '',
option2: '',
value1: 1,
value2: '',
value3: 3,
}
}
handleChange = e => {
let nextState;
if (e.target) {
const { name, value } = e.target;
nextState = { [name]: value };
} else if (e.selectedValue) {
const { name, selectedValue } = e;
nextState = { [name]: selectedValue };
}
this.setState(nextState);
}
render() {
const { value1, value2, value3, option1, option2 } = this.state;
return (
<div>
<MySelect
value={option1.value}
onChange={this.handleChange}
options={options}
name="option1"
/>
<div>
<span>input1 </span>
<input value={value1} name="value1" onChange={this.handleChange} />
</div>
<div>
<span>input2 </span>
<input value={value2} name="value2" onChange={this.handleChange} />
</div>
<div>
<span>input3 </span>
<input value={value3} name="value3" onChange={this.handleChange} />
</div>
<MySelect
value={option2.value}
onChange={this.handleChange}
options={moreOptions}
name="option2"
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/prop-types#15.5.10/prop-types.js"></script>
<script src="https://unpkg.com/classnames#2.2.5/index.js"></script>
<script src="https://unpkg.com/react-input-autosize#2.0.0/dist/react-input-autosize.js"></script>
<script src="https://unpkg.com/react-select/dist/react-select.js"></script>
<link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css">
<div id="root"></div>

Categories

Resources