Dropdown not expanding even after having values - reactjs

I am facing an issue where my 2nd dropdown is receiving values but is not expanding:-
class clusterServersDropdown extends Component {
constructor() {
super();
this.state = {
clusterslist: [],
servertype: [],
selectserver: "",
selectcluster: ""
};
}
componentDidMount() {
this.setState({
clusterslist:[
{label: "cluster1", servertype:["test1","test2","test3"]},
{label: "cluster2", servertype:["test1","test2","test3"]},
{label: "cluster3", servertype:["test1","test2","test3"]},
]
});
}
selectclusterChange(e) {
console.log(e.label)
this.setState({ selectcluster: e.label },() =>{
console.log(this.state.selectcluster)
});
this.setState({
servertype: this.state.clusterslist.find(
(x) => x.label === e.label
).servertype
},() =>{
console.log(this.state.servertype)
}
);
}
routeChange = (e) => {
console.log(e.label)
this.setState({ selectserver: e.label}, () => {
console.log(this.state.selectserver);
let path = "/inventory/cluster/" + this.state.selectcluster +"/servertype/" + this.state.selectserver;
console.log(path);
this.props.history.push(path);
});
};
render() {
return (
<div>
<center>
<label>
Select cluster and server type
<Select className="react-select" classNamePrefix="react-select"
onChange={this.selectclusterChange.bind(this)}
options={this.state.clusterslist.map((x) => {
return {label: x.label};
})}
/>
<Select className="react-select" classNamePrefix="react-select"
onChange={this.routeChange.bind(this)}
options={this.state.servertype.map((y) => {
return {label: y};
})}
/>
</label>
</center>
</div>
);
}
}
export default withRouter(clusterServersDropdown);
Please see below snaps:-
Whenever I am clicking on the 2nd dropdown it retracts and am not able to select the value and proceed. Strangely this works if i replace label by h5, see as below:-
Am i using label wrongly?

Removed label and used h5 with some font formatting instead.
render() {
return (
<div>
<center>
<h5 style={{'font-family':"Pacifico"}}>
Select cluster and server type from dropdown to view its inventory
<Select className="react-select" classNamePrefix="react-select"
onChange={this.selectclusterChange.bind(this)}
options={this.state.clusterslist.map((x) => {
return {label: x.label};
})}
/>
<Select className="react-select" classNamePrefix="react-select"
onChange={this.routeChange}
options={this.state.servertype.map((y) => {
return {label: y};
})}
/>
</h5>
</center>
</div>
);
}
}
Working as expected now.

Related

I want to clear the text fields once I click on filter button

In this code I am unable to clear both the text fields even though I'm setting their states to blank after clicking on filter via this.Search function.
import React from 'react' import Axios from './Axios' import
'./index.css' export default class Practise extends React.Component {
constructor(props) {
super(props)
this.state = {
lists: [],
names: '',
emails: '',
arr: [],
}
this.Search = (names, emails) => {
const arr = this.state.lists.filter(item => {
if (item.name.includes(this.state.names) && item.email.includes(this.state.emails)) {
return true
} else {
return false
}
})
this.setState({names:''})
this.setState({emails:''})
console.log(arr)
}
}
componentDidMount() {
Axios.get('/comments').then(response => {
// console.log(response.data, 'data')
this.setState({ lists: response.data })
}).catch(response => {
console.log(response, 'Errored!!!')
this.setState({ errored: 'Error has Occured' })
})
}
render() {
const { lists, arr, names, emails } = this.state
return (
<>
<div >
<input type='text' onChange={(e) => this.setState({ names: e.target.value })} />
<input type='text' onChange={(p) => this.setState({ emails: p.target.value })} />
<button onClick={()=>this.Search()}>Filter</button>
</div>
<div>
{lists.length ? lists.map(item =>
<div className='divone' key={item.id}>
Id:- {item.id} <br />
Name:- {item.name} <br />
Email:- {item.email}</div>) : null}
</div>
</>
)
}
};
You have to add the value prop to both of the inputs.After that,
if you change the state to a blank string, the value of inputs will also get blank.Here is an example -
<input type='text' value={this.state.names} onChange={(e) => this.setState({ names: e.target.value })} />
<input type='text' value={this.state.emails} onChange={(p) => this.setState({ emails: p.target.value })} />
It should work.

react - this = undefined, how to pass the prop into my function

I have passed my user ID into my 'OrderMessages' component but in my function says undefined. When my user submits a messages using the form in the handleFormSubmit function I need the UserID and the datetime of the message. I have managed to get the date and time but when trying to console log to get the UserID I keep getting an error. I have tried this.props.... and this.state but both say undefined, can you please help. In my constructor I have tested using const UserId = props.location.state.UserID; and in debug I can see this has correctly got the UserID so im not sure how to get it into my hadleFormSubmit function.
import React from "react";
import Moment from "moment";
import { Form, Button } from "react-bootstrap";
class OrderMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: false,
checkboxes: [],
selectedId: [],
formLableSelected: "",
formSelectedSubject: "",
formSelectedSubjectId: "",
formNewSubject: "",
formChainID: "",
formMessageBody: "",
userId: '',
};
const UserId = props.location.state.UserID;
}
componentDidMount() {
this.setState({ isLoading: true });
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url =
"myURL" +
this.props.location.state.orderNumber;
fetch(proxyurl + url)
.then((res) => res.json())
.then((data) => this.setState({ data: data, isLoading: false }));
}
handleClick = (id) => {
if (this.state.selectedId !== id) {
this.setState({ selectedId: id });
} else {
this.setState({ selectedId: null });
}
};
setformSubjectID(messageSubject) {
if (messageSubject.subject === this.state.formSelectedSubject) {
this.setState({ formSelectedSubjectId: messageSubject.messageSubjectId });
}
}
handleChangeSubject = (event) => {
this.setState({ formSelectedSubject: event.target.value });
this.state.data.message_Subjects.map((ms) => this.setformSubjectID(ms));
};
handleFormSubmit(e) {
e.preventDefault();
// get current time
let submit_time = Moment().format("ddd DD MMM YYYY HH:mm:ss");
console.log("messageDatetime", submit_time);
// get user id THIS IS WHAT DOESN’T WORK
console.log("messageSentFrom", this.state.userId);
console.log("messageSentFrom", this.props.location.state.UserID);
}
render() {
const { data, isLoading } = this.state;
if (isLoading) {
return <p>Loading ...</p>;
}
if (data.length === 0) {
return <p> no data found</p>;
}
console.log("mess: ", data);
return (
<div>
<div className="sendMessageContent">
<Form className="sendMessageForm" onSubmit={this.handleFormSubmit}>
<Form.Group className="formRadio">
<Form.Check
className="formRadiob"
type="radio"
label="New chat"
value="new"
name="neworexisitng"
id="New Message"
onChange={this.onFormMessageChanged}
defaultChecked
/>
<Form.Check
className="formRadiob"
type="radio"
label="Reply to exisiting chat"
value="reply"
name="neworexisitng"
id="exisiting Message"
onChange={this.onFormMessageChanged}
/>
</Form.Group>
{this.returnCorrectFormFields(data)}
<Form.Group>
<Form.Label>Message Body</Form.Label>
<Form.Control as="textarea" rows={3} />
</Form.Group>
<Button variant="primary" type="submit">
Send Message
</Button>
</Form>
</div>
</div>
);
}
returnCorrectFormFields(data) {
if (this.state.formLableSelected === "new") {
return this.newMessageSubject(data);
} else {
return this.choseMessageSubject(data);
}
}
choseMessageSubject(data) {
return (
<Form.Group>
<Form.Label>Select the message subject</Form.Label>
<Form.Control as="select" onChange={this.handleChangeSubject}>
<option value="0">Choose...</option>
{data.message_Subjects.map((ms) => (
<option value={ms.subject}>{ms.subject}</option>
))}
</Form.Control>
</Form.Group>
);
}
newMessageSubject(data) {
return (
<Form.Group>
<Form.Label>Enter Message Subject</Form.Label>
<Form.Control type="text" placeholder="Enter message subject" />
</Form.Group>
);
}
onFormMessageChanged = (event) => {
this.setState({
formLableSelected: event.target.value,
});
};
getAllMessageInChain(messageChain) {
return (
<div className="messageHistory">
<div className="messageHistoryHeader">
<div className="innerMS-history-body">Message</div>
<div className="innerMS">Date and Time</div>
<div className="innerMS">Message sent by</div>
</div>
{messageChain.map((ms) => (
<div className="messageHistoryBody">
<div className="innerMS-history-body">{ms.messageBody}</div>
<div className="innerMS">
{Moment(ms.dateTime).format("ddd DD MMM YYYY hh:mm:ss")}
</div>
<div className="innerMS">{ms.sentFromId}</div>
</div>
))}
</div>
);
}
getLatestMessageDateTime(messageChain) {
const lastmessage = messageChain.length - 1;
Moment.locale("en");
var dt = messageChain[lastmessage].dateTime;
return Moment(dt).format("ddd DD MMM YYYY hh:mm:ss");
}
}
export default OrderMessages;
The scope of this isn't the component in the function you're using.
Either change handleFormSubmit to this to bind this automatically.
handleFormSubmit = (e) => {
// .. your code
}
or bind this manually in the constructor
constructor() {
// ..other code
this.handleFormSubmit = this.handleFormSubmit.bind(this)
}

Radio buttons for redux form field

It doesn't work correctly, I want to select only one value, but I can select one and more... and can't deselect
there is code for that function.
const RadioButtonField = ({type, options, disabled, onChange}) => {
const handleChange = (value) => {
onChange(type, value);
};
return (
<div>
{options.map(({ value, label }) =>
<Radio.Group key={value}>
<Radio
disabled={disabled}
onChange={() => handleChange(value)}
>
{label}
</Radio>
</Radio.Group>
)}
</div>
);
};
You can try this for single selection and also you can reselect too
import React from "react";
import "./styles.css";
import Radio from "#material-ui/core/Radio";
export default class App extends React.Component {
state = {
selectedValue: null,
radioOptions: [
{ id: 1, title: "1" },
{ id: 2, title: "2" },
{ id: 3, title: "3" },
{ id: 4, title: "4" }
]
};
handleChange = id => {
this.setState({
selectedValue: id
});
};
render() {
const { selectedValue, radioOptions } = this.state;
return (
<div className="App">
{radioOptions.map(option => {
return (
<div className="radio-parent">
<lable
onClick={() => this.handleChange(option.id)}
className="radio-btn"
>
<Radio
color="default"
value={option.id}
name="radioValue"
checked={selectedValue == option.id}
/>
{option.title}
</lable>
</div>
);
})}
</div>
);
}
}
codesandBox link for Demo
You can refer to the following code:
class App extends React.Component {
state = {
initialValue: "A",
options: ["A", "B", "C", "D"]
};
onChange = e => {
console.log("radio checked", e.target.value);
this.setState({
value: e.target.value
});
};
render() {
return (
<Radio.Group value={this.state.initialValue}>
{this.state.options.map((value, index) => {
return (
<Radio onChange={this.onChange} key={index} value={value}>
{" "}
{value}{" "}
</Radio>
);
})}
</Radio.Group>
);
}
}
Working codesandbox demo
I think you do not need to pass anything to the function. Whenever the option will be clicked, the event (e) object will be passed to onChange(e) and you will get the value of clicked item and checked value in onChange(e) e.target.value and e.target.checked respectively.

Why is my to do list failing to update when state is being updated?

I'm writing a simple to do list app, but the functional component that maps the to-do items in the array is not running again after rendering the initial items and I add another one and I don't' know why.
I can see in the console that the state is being updated with a new item, so I'm just stuck wondering why it's not displaying on the page when I add a new item.
import React from 'react';
class App extends React.Component {
state = { items: [
{
id: 1,
item: 'code another react app'
},
{
id: 2,
item: 'eat some cheetos'
}
],
inputVal: ''
}
onFormSubmit = (e) => {
e.preventDefault();
let newId = Math.random();
let newItem = this.state.inputVal;
this.setState({
items: [
...this.state.items,
{id: newId, item: newItem }
],
inputVal: ''
})
}
toDoList = this.state.items.map(item => {
console.log(item)
return (
<div key={item.id}>
<li>{item.item}</li>
</div>
)
})
render() {
console.log(this.state)
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input
placeholder="add a to do item"
value={this.state.inputVal}
type="text"
onChange={e => this.setState({ inputVal: e.target.value })}
/>
</form>
{this.toDoList}
</div>
);
}
}
export default App;
The toDoList variable is set only one time.
you have to use in render method.
render() {
const toDoList = this.state.items.map(item => {
console.log(item)
return (
<div key={item.id}>
<li>{item.item}</li>
</div>
)
})
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input
placeholder="add a to do item"
value={this.state.inputVal}
type="text"
onChange={e => this.setState({ inputVal: e.target.value })}
/>
</form>
{toDoList}
</div>
);
}

Passing a function as a prop in react, Cannot read property 'edit' of undefined

I'm learning ReactJS and I'm creating a editable Pokémon list based on this guide.
When I try to pass a function to edit a list item (at this point I want to click the item and get the name), I get TypeError: Cannot read property 'edit' of undefined on the following line of the addPokemon function: onClick={() => this.edit(pokemon.name)}
Code:
PkmnForm
import React, { Component } from "react";
import PkmnList from "./PkmnList";
class PkmnForm extends Component {
static types = [
'Bug',
'Dragon',
'Ice',
'Fighting',
'Fire',
'Flying',
'Grass',
'Ghost',
'Ground',
'Electric',
'Normal',
'Poison',
'Psychic',
'Rock',
'Water'
]
constructor(props) {
super(props);
this.state = {
name: '',
type: '',
pokemons: [],
caught: false,
};
}
handleSubmit = (event) => {
var pokemon = {
name: this.state.name,
type: this.state.type,
caught: this.state.caught
};
this.setState({
name: '',
type: '',
caught: false,
pokemons: this.state.pokemons.concat(pokemon)
});
event.preventDefault()
}
handleChange = (event) => {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleTypeChange = (event) => {
this.setState({
type: event.target.value,
})
}
editPokemon(name) {
console.log(name);
}
render() {
return (
<div>
<div>
<h1>Register a Pokémon</h1>
<form onSubmit={this.handleSubmit}>
<input
required
placeholder=" Name"
name="name"
onChange={this.handleChange}
value={this.state.name}
/>
<br />
<select
name="type"
required
value={this.state.type}
onChange={this.handleChange}
>
<option value='' disabled>Type</option>
{PkmnForm.types.map(
optionValue => (
<option
key={optionValue}
value={optionValue}
>
{optionValue}
</option>
)
)}
</select>
<br />
<label>
Caught
<input
name="caught"
type="checkbox"
checked={this.state.caught}
onChange={this.handleChange}
/>
</label>
<br />
<button type="submit">Add Pokemon</button>
</form>
</div>
<div>
<PkmnList
pokemons={this.state.pokemons}
edit={this.editPokemon}
/>
</div>
</div>
);
}
}
export default PkmnForm;
PkmnList
import React, { Component } from 'react';
class PkmnList extends Component {
constructor(props) {
super(props);
this.edit = this.edit.bind(this);
}
edit(name) {
this.props.edit(name);
}
addPokemon(pokemon) {
return <li
onClick={() => this.edit(pokemon.name)}
key={pokemon.name}
>
{pokemon.name} – {pokemon.type} {pokemon.caught ? '(caught)' : ''}
</li>
}
render() {
var pokemons = this.props.pokemons;
var listItems = pokemons.map(this.addPokemon);
return (
<ul>
{listItems}
</ul>
);
}
}
export default PkmnList;
Thanks :-)
The problem is in this line:
var listItems = pokemons.map(this.addPokemon);
Here, you are passing this.addPokemon as the function to map. But that function is not bound to this, so inside of it, this is not available.
You either have to bind it explicitly by calling .bind(this), just like you did with the edit function:
var listItems = pokemons.map(this.addPokemon.bind(this));
Or you can pass an arrow function that calls the method:
var listItems = pokemons.map(x => this.addPokemon(x));
You need to bind editPokemon like so:
constructor(props) {
super(props);
this.editPokemon = this.editPokemon.bind(this);
}
Or you can also use arrow functions, which have proper scoping:
editPokemon = (pokemon) => {
...
}

Resources