How to set placeholder for dropdown in react js? - reactjs

<select>
<option selected disabled>Select</option
I added an extra option with a disabled property, but this gives me the following warning:
Use the defaultValue or value props on select instead of setting
selected on option.
<select>
{this.props.optionarray.map(function(e){
return <option
value={e[self.props.unique]}
key={e[self.props.unique]}
>
{e[self.props.name]}
</option>
})}
</select>
optionarray is an array which is passed through props to be mapped on each index which has an object and I pass the key through props as well which was in the array. Everything is working here, it's just showing me the warning that I mentioned above.
How do I remove that or how do I set a perfect placeholder for a dropdown in react?

Reason is, React provide a better way of controlling the element by using states, so instead of using selected with option use the value property of select and define its value in the state variable, use the onChange method to update the state, Use it in this way:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '1'
};
}
render(){
return(
<select value={this.state.value} onChange={(e)=>{this.setState({value: e.target.value})}}>
<option value='1' disabled>Select</option>
{
[2,3,4].map((i,j)=>{
return <option key={i} value={i}>{i}</option>
})
}
</select>
);
}
}
How to set placeholder for dropdown?
According to Mozilla Dev Network, placeholder is not a valid attribute on a <select>. So in place of that you can you this also to render a default option:
<option default>Select</option>
Use of key as per DOC:
Keys help React identify which items have changed, are added, or are
removed. Keys should be given to the elements inside the array to give
the elements a stable identity.
Suggestion:
Whenever we create any ui dynamically in loop, we need to assign a unique key to each element, so that react can easily identify the element, it basically used to improve the performance.
Check the working example:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '1'
};
}
render(){
return(
<select value={this.state.value} onChange={(e)=>{this.setState({value: e.target.value})}}>
<option value='1' disabled>Select</option>
{
[2,3,4].map((i,j)=>{
return <option key={i} value={i}>{i}</option>
})
}
</select>
);
}
}
ReactDOM.render(<App />, document.getElementById('container'));
<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>
<div id='container'/>
Check the fiddle for working example: https://jsfiddle.net/29uk8fn0/

Functional Component
import { useState } from "react";
export default function DropdownComponent(props) {
const [formData, setFromData] = useState({
anyInput: "something",
dropdownInput: null,
});
return (
<>
anyInput: { formData.anyInput }
dropdownInput: { formData.dropdownInput }
<select name={"dropdownName"} onChange={ ({target})=> {
setFromData((prev)=> ({...prev, dropdownInput:target?.value}) );
}
}>
<option key='blankKey' hidden value >Placeholder Text for Select</option>
{
[2,3,4].map((i,j)=>{
return <option key={i} value={i}>{i}</option>
})
}
</select>
</>
)
}

Related

ReactJs: Rendering Similar React Components from a list without using same states for each of the element

I have a CustomReactComponent class which holds a list of similar React Components, I then render a single element Component from the list based on some condition.
This Component has <input/> tag.
When I try to render it all the <input/> tags have the same value when User changes only one of them.
How can I prevent this from happening? and have the inputs store differnt values for each instance
Minimal Reproducible Code:
import {Component} from "react";
export default class CustomReactComponent extends Component {
constructor(props) {
super(props);
this.state = {selected: 0};
this.list = [<div><input/></div>, <div><input/></div>, <div><input/></div>, <div><input/></div>];
}
onSelect = (e) => {
this.setState({selected: e.target.value});
}
render() {
let Component = this.list[this.state.selected];
return (
<div>
<select onChange={this.onSelect}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div>
State:{this.state.selected}:
{Component}
</div>
</div>
);
}
}
Edit 1:
As #asynts pointed out we could use key for each component, but keys's check for siblings during rendering, and since here i am rendering only a single component, key would be of no use, it re-initializes the component every time the state selected changes. But this is a start, it atleast dosent treat all the components in this.list as the same thing
Edit 2:
After some tinkering and experimentation I found a work around for this, we can have a Wrap Component which is given a unique id uid as a prop this can then be used during rendering if state selected points to uid of a Wrap we style it to display: initial else to display: none, this is where key's comes handy we can always render all the siblings and give it a key same as uid
Code:
import {Component} from "react";
function Wrap({uid}) {
return <div>uid = {uid} : <input/></div>
}
export default class CustomReactComponent extends Component {
constructor(props) {
super(props);
this.state = {selected: 0};
this.list = [
<Wrap uid={0}/>,
<Wrap uid={1}/>,
<Wrap uid={2}/>,
<Wrap uid={3}/>
];
}
onSelect = (e) => {
this.setState({selected: parseInt(e.target.value)});
}
render() {
return (
<div>
State:
<select onChange={this.onSelect}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div>
{this.list.map((component) =>
<div key={component.props.uid}
style={{display: component.props.uid !== this.state.selected ? 'none' : 'initial'}}>
{component}
</div>)}
</div>
</div>
);
}
}
This is actually a much more interesting problem than I originally thought.
It seems that React simply can't tell that you are rendering a different element.
Ultimately, the JSX syntax is just syntactic sugar for React.createElement which returns an object:
// jsx:
<input />
// js:
React.createElement("input");
// result object:
{
type: "input",
// This is the default.
key: null,
// There is some other stuff in here too.
}
In other words, all the entries in your array are identical as far as React is concerned.
You can resolve this problem by specifying a key attribute in each array entry:
this.list = [
<div key="1"><input/></div>,
<div key="2"><input/></div>,
<div key="3"><input/></div>,
<div key="4"><input/></div>,
];
There is some documentation about this but it's a bit vague.
Here is an in-depth explanation about why keys are necessary if you’re interested in learning more.
TL;DR: React will create a tree of these objects I mentioned and then computes the difference to the previous tree and updates the DOM. In your case, it is not able to find a difference and therefore needs the key attribute to help.
We could use key for each component, but key's check for siblings during rendering, and here only a single component is being rendered, thus making key not so useful, it re-initializes the component every time the state selected changes.
But we can have a Wrap Component as a work around, Wrap is given a unique id uid as a prop this can then be used during rendering if state selected points to uid of a Wrap we style it to display: initial else to display: none, this is where key's comes handy we can always render all the siblings and give it a key same as uid
Code:
import {Component} from "react";
function Wrap({uid}) {
return <div>uid = {uid} : <input/></div>
}
export default class CustomReactComponent extends Component {
constructor(props) {
super(props);
this.state = {selected: 0};
this.list = [
<Wrap uid={0}/>,
<Wrap uid={1}/>,
<Wrap uid={2}/>,
<Wrap uid={3}/>
];
}
onSelect = (e) => {
this.setState({selected: parseInt(e.target.value)});
}
render() {
return (
<div>
State:
<select onChange={this.onSelect}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div>
{this.list.map((component) =>
<div key={component.props.uid}
style={{display: component.props.uid !== this.state.selected ? 'none' : 'initial'}}>
{component}
</div>)}
</div>
</div>
);
}
}

how to open a textfield and set its value on select some value in dropdown in react

I am trying to display a textbox based on some selected value in dropdown in react.
my code is
<label>
color:
<select value="Radish" onChange ={this.checkColor}>
<option value="Orange">Orange</option>
<option value="Radish">Radish</option>
<option value="Cherry">Cherry</option>
</select>
<input type="text" name="project Id" id="project Id" style={{display:'none'}}/>
<label>
Onchange, the below function will be invoked.
CheckLayers(evt){
if(evt.target.value === 'Orange'){
this.setState({showField:true})
}
}
But I am not able to see the textbox. I tried to put condition based on showField but that's not working.
(this.state.showField)
<input type="text" name="project Id" id="project Id" style={{display:'none'}}/>
Please advice!!
There are a few things to check in your code.
First, with your current implementation of the <select> and <option> elements, the actual value on the <select> will never change because it is always set to "Orange". You need to also save the last selected <select> value in your component's state:
checkLayers(event) {
const { value } = event.target;
this.setState({
showField: value === "Orange",
selectedValue: value
});
};
And in your render method use the selectedValue accordingly:
render() {
return (
<label>
color
<select value={this.state.selectedValue} onChange={this.checkLayers}>
/* {your options} */
</select>
</label>
);
}
The next thing to check is the checkLayers method. Inside this method you are trying to access this. Since the <select>'s onChange callback is going to be called on a different context as your component (you can check this by logging this inside checkLayers). As a result of this, you need to bind the checkLayers method to your component's context. This can be done by explicitly binding the function when passing it as a callback or by defining the class method as an arrow function.
Binding option (in the render method):
<select value={selectedValue} onChange={this.checkLayers.bind(this)}>
Class method as Arrow function option:
class MyComponent extends React.Component {
...
checkLayers = (event) => {
const { value } = event.target;
this.setState({
showField: value === "Orange",
selectedValue: value
});
};
...
There is also an alternative option using arrow functions:
<select value={selectedValue} onChange={(event) => this.checkLayers(event)}>
You can learn more about thishere
The last thing to check is how you are trying to conditionally render the <input> element. Right now you are hardcoding the style as { display: 'none' }. You could change this based on the value of showField, but I think is it better only render the <input> when showField is true, like this:
render() {
const { selectedValue, showField } = this.state;
return (
<label>
color:
<select value={selectedValue} onChange={this.checkLayers.bind(this)}>
/* {your options} */
</select>
{showField ? (
<input
type="text"
name="project Id"
id="project Id"
/>
) : null}
</label>
);
}
Here we are using the ternary operator to decide if we render the element or we render nothing (using null).
You can see the final implementation here:
Comment if you have further questions, cheers!

React change initial state based on another field value

How can I change the initial state value of a field based on the input value of another field?
Here's my code:
import React from "react";
export class someComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
grade: "",
tuition: changeStateHere
};
}
render() {
<div>
<form onSubmit={this.someFunction.bind(this)}>
<select name="grade" onChange={this.onChange} value={this.state.grade}>
<option value="">Class</option>
<option value="Grade One">Grade One</option>
<option value="Grade Two">Grade Two</option>
<option value="Grade Three">Grade Three</option>
<option value="Grade Four">Grade Four</option>
<option value="Grade Five">Grade Five</option>
<option value="Grade Six">Grade Six</option>
</select>
<input
type="text"
name="tuition"
placeholder="Tuition"
value={this.state.tuition}
onChange={this.onChange}
/>
</form>
</div>;
}
}
I want to set a dynamic initial state value for tuition based on input option on the grade select field.
For example, if a user selects Grade One, the tuition value should be 15000; if Grade Two, the value should be '20000'; etc.
Is there any workaround dynamically changing the initial state value?
Everything inside of the constructor is run before render. You're not going to be able to set a different initial value to the state based on something inside the render method.
Also move away from binding functions in the render method. it would be better to use a class method someFunction = () => {} and then attach it inside the JSX as onSubmit={this.someFunction}
Each time the component re-renders another instance of someFunction is bound which will eventually lead to performance issues in the browser.
You need to handle the grade selection and evaluate the event.target.value of the select element. Based on this you can use a switch to this.setState both Tuition and whether or not the input field is disabled. You should use defaultValue instead of value so that when the user picks and option it sets the input to this.state.tuition
import React from "react";
export class someComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
grade: "",
gradeSelected: false,
tuition: 0,
};
}
handleGradeSelect = event => {
let newState = Object.assign({}, this.state) // duplicate state so you can mutate this copy
switch(event.target.value){ // evaluate the value of the select option
case 'Grade One':
newState.tuition = 15000
case 'Grade Two':
newState.tuition = 20000
// You get the picture
default:
newState.tuition = 0 // needs to have a default if no option
}
newState.gradeSelected = true
this.setState(newState)
}
render() {
<div>
<form onSubmit={this.someFunction.bind(this)}>
<select name="grade" onChange={event => this.handleChange(event)}>
<option disabled>Class</option>
<option value="Grade One">Grade One</option>
<option value="Grade Two">Grade Two</option>
<option value="Grade Three">Grade Three</option>
<option value="Grade Four">Grade Four</option>
<option value="Grade Five">Grade Five</option>
<option value="Grade Six">Grade Six</option>
</select>
<input
type="text"
name="tuition"
placeholder="Tuition"
value={this.state.tuition}
onChange={this.onChange}
disabled={!this.state.gradeSelected}
/>
</form>
</div>;
}
}

reactjs change state of select with out clicking on it

I have the following select component in my react program:
<select>
<option>option1</option>
<option>option2</option>
</select>
I'd like to be able to change which option is selected when some event takes place, say pressing a button, in addition to being able to change which option is selected by interacting with the drop down menu. How can I do this? Here is an example of what I mean:
<select>
<option>option1</option>
<option>option2</option>
</select>
<button/> // when this button is pressed I want
// the selected option to change to option1
// regardless of the selects current state
Thanks
Please note: I am not asking how to change the default state of the select, I want to be able to change it at run time by pressing a button
Set a state variable to control the selected value and then update that state variable onClick of a button.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedOption: ""
};
}
handleChange = event => {
this.setState({selectedOption: event.target.value});
}
handleClick = () => {
this.setState({selectedOption: "foo"});
}
render() {
return (
<div className="App">
<select value={this.state.selectedOption} onChange={this.handleChange}>
<option value="">Default</option>
<option value="foo">Foo</option>
<option value="bar">Bar</option>
</select>
<button onClick={this.handleClick}>Click Me</button>
</div>
);
}
}
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>
<div id='app' />

How to automaticaly setState in an onChange event in a select-dropdown, as currently the event is triggered only when the user clicks on the list?

Currently, the default state is empty and is updated only when the user clicks on the drop-down triggering the onChange event. How do I make it so that the item selected by default is also set to the state? So the first option is selected by default in the drop-down, and I'd like to set the first option in the state automatically.
this.state = { slug: '' }
<select>
data && data.map((datum, i) => { return (
<option
value={datum.id}
key={i}
onChange={e => this.setState({ slug: datum.slug })}>
{datum.name}
</option>
)})}
<select>
You can define the default value in the state
this.state = { slug: 'zero' }
and then tells react to set that value in the select
<select value={this.state.slug}>
<option value="zero">Zero</option>
<option value="one">One</option>
<option value="two">Two</option>
</select>
If you want to programmatically select the first value, you can write this.
<select>
data && data.map((datum, i) => {
const isSelected = this.state.slug === '' && i === 0;
return (
<option
selected={isSelected}
value={datum.id}
key={i}
onChange={}
>
{datum.name}
</option>
)})}
</selected>
If you want your state to reflect your default option, you can do that in the constructor of the component.
constructor(props){
super(props);
this.state = {
slug : this.props.data[0].id
}
}
After that you can use one of the solutions I mention before to handling the select component.
If you change data often, you can do that inside componentWillReceiveProps instead of constructor, but the idea it's the same.

Resources