state.map(state, i) gives undefined - javascript

Hello I am trying to render out options based on an array that I have in my state using map but I get undefined when using it in the return
Here is the array
this.state = { countries: ["Australia","Brazil","China","Sweden"]}
I try to use it as such
this.state.countries.map((country, i) =>
<option value={this.state.countries[i]}>{this.state.countries[i]}</option>)
but I get i is undefined. I also try to use country only but always get undefined. But if i in my render do like this
this.state.countries.map((country, i) => console.log(country + " " + i));
I get it perfect both the country and the i is correct. Why cant i use the values in the return?
Here is the whole component
class BoxForm extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
weight: "",
color: "",
country: "",
countries: ["Australia","Brazil","China","Sweden"]
}
this.handleNameChange = this.handleNameChange.bind(this);
this.handleWeightChange = this.handleWeightChange.bind(this);
}
handleNameChange(e) {
this.setState({ name: e.target.value });
}
handleWeightChange(e) {
this.setState({ weight: e.target.value });
}
render() {
this.state.countries.map((country, i) => console.log(country + " " + i));
return (
<div className="formGroup">
<form>
<FormGroup>
<h4 className="nameHeader">Name</h4>
<FormControl
className="textfield"
type="text"
value={this.state.name}
placeholder="Enter text"
onChange={this.handleNameChange}
/>
<h4 className="weightHeader">Weight</h4>
<FormControl
className="textfield"
type="number"
value={this.state.weight}
placeholder="Enter text"
onChange={this.handleWeightChange}
/>
<h4 className="colorHeader">Box Color</h4>
<FormControl
className="textfield"
type="text"
value={this.state.color}
placeholder="Enter text"
/>
<h4 className="destinationHeader">Destination Country</h4>
<FormControl
componentClass="select"
className="textfield"
type="dropdown"
value={this.state.country}
placeholder="Enter text"
>
this.state.countries.map((country, i) =>
<option value={this.state.countries[i]}>{this.state.countries[i]}</option>)
</FormControl>
</FormGroup>
</form>
</div>
);
}
}
export default BoxForm;

You need to wrap your returned from map array with {}
<FormControl
componentClass="select"
className="textfield"
type="dropdown"
value={this.state.country}
placeholder="Enter text"
>
{this.state.countries.map((country, i) => (
<option value={country}>{country}</option>
))}
</FormControl>;

Please check the working select option component created :).
https://codesandbox.io/s/xjpw5wq65w
import React, { Component } from "react";
class SelectOptionComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: "",
countries: ["Australia", "Brazil", "China", "Sweden"]
};
}
handleChange = e => {
const { value } = e.target;
this.setState({
value: value
});
console.log("Selected Item", value);
};
renderData() {
return this.state.countries.map((item, index) => {
return (
<option value={item} key={index}>
{item}
</option>
);
});
}
render() {
return (
<select value={this.state.value} onChange={this.handleChange}>
{this.renderData()}
</select>
);
}
}
export default SelectOptionComponent;

Related

How to iterate through array that is value of key in JSON

I have JSON file like this
[
{
"id": 1,
"country": "Afghanistan",
"city": ["Eshkashem","Fayzabad","Jurm","Khandud"]
},
{
"id": 2,
"country": "Italy",
"city": ["Milano","Rome","Torino","Venezia"]
}
]
and I want to iterate through array placed in the city. Idea is to have two selects, where the first select is reserved for countries and the second is reserved for cities. Whenever the user selects a country, I want to populate the second select with a list of cities. Problem is that I receive only one array of all cities for that country. Here is my code:
export default class DiffCountries extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
contacts: [],
selectedCountry: [],
selectedCity: []
}
}
onChangeHandler = (event) => {
const test = CountriesData[event.target.value - 1];
this.setState({
selectedCountry: test,
selectedCity: this.state.selectedCountry.city
})
console.log(this.state.selectedCity);
}
render() {
const { contacts } = this.state;
return (
<div>
<select name="" id="" onChange={this.onChangeHandler}>
{CountriesData.map(item => {
const { id, country } = item;
return <option key={id} value={id}>{country}</option>
})}
</select>
<select name="" id="">
{this.state.selectedCountry !== undefined ?
<option value="">{this.state.selectedCountry.city}</option> :
null
}
</select>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
And here is the screenshot of my problem
Thank you in advance!
You need to use map() on the city array.
<select name = "" id = "" > {
this.state.selectedCountry !== undefined ?
this.state.selectedCountry.city.map((x,i) => <option value={x} key={i}>{x}</option>)
:null
}
</select>
You need to iterate through the array.
this.state.selectedCountry.city.map((city, index) => {
return <option value={city} key={index}>{city}</option>
})
Be aware, that using the index as a key is considered an anti pattern. You could use the name of the city as a key as well. E.g.:
this.state.selectedCountry.city.map(city => {
return <option value={city} key={city}>{city}</option>
})
edit to add link to mdn docs as suggested in comments: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Example:
const CountriesData = [
{
id: 1,
country: 'Afghanistan',
city: ['Eshkashem', 'Fayzabad', 'Jurm', 'Khandud'],
},
{
id: 2,
country: 'Italy',
city: ['Milano', 'Rome', 'Torino', 'Venezia'],
},
];
class DiffCountries extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedCountry: null,
};
}
onChangeHandler = event => {
const selectedCountry = CountriesData[event.target.value - 1];
this.setState({
selectedCountry,
});
};
render() {
const { selectedCountry } = this.state;
return (
<div>
<select
name="country"
defaultValue="country"
onChange={this.onChangeHandler}
>
<option disabled value="country">
Select country
</option>
{CountriesData.map(({ id, country }) => (
<option key={id} value={id}>
{country}
</option>
))}
</select>
{selectedCountry && (
<select name="city" defaultValue="city">
<option disabled value="city">
Select city
</option>
{selectedCountry.city.map(item => (
<option key={item} value={item}>
{item}
</option>
))}
</select>
)}
</div>
);
}
}
ReactDOM.render(<DiffCountries />, document.getElementById('container'));

front-end just remove only last item in array

I'm having a issue with React.
my parent component:
class RoomPrice extends React.Component {
constructor(props){
super(props)
this.state = {
room: this.props.room,
prices: []
};
this.handleDeletePrice = this.handleDeletePrice.bind(this);
}
handleDeletePrice(price_index){
let prices = this.state.prices;
prices.splice(price_index, 1);
this.setState({prices: prices});
}
listPrices(){
console.log(this.state.prices)
return this.state.prices.map((item, index) => {
return (
<AdditionalPrice
key={index}
price={item}
index={index}
handleDeletePrice={this.handleDeletePrice}
/>
)
});
}
renderBasePrice(){
return(
<div id="list_prices">
{ this.listPrices() }
</div>
)
}
render(){
return(
<div>
{this.renderBasePrice()}
</div>
)
}
}
my child component
class AdditionalPrice extends React.Component {
constructor(props){
super(props)
this.state = {
price: this.props.price
}
this.handleKeyChange = this.handleKeyChange.bind(this);
this.handleValueChange = this.handleValueChange.bind(this);
this.handleDeletePrice = this.handleDeletePrice.bind(this);
}
componentWillReceiveProps(nextProps){
this.setState({price: nextProps.price})
}
handleKeyChange(event){
let price = this.state.price;
price.key = event.target.value
this.setState({price: price})
}
handleValueChange(event){
let price = this.state.price;
price.value = event.target.value
this.setState({price: price})
}
handleDeletePrice(){
this.props.handleDeletePrice(this.props.index);
}
renderForm(){
let key = this.state.price.key;
let value = this.state.price.value;
return(
<div className="form-row">
<div className="col-5">
<input type="text" className="form-control" placeholder="Key" onChange={this.handleKeyChange} required/>
</div>
<div className="col-5">
<input type="number" className="form-control" placeholder="Value" onChange={this.handleValueChange} required/>
</div>
<div className="col-2">
<button className="btn btn-warning" type="button" onClick={this.handleDeletePrice}>
<i className="material-icons">delete_forever</i>
</button>
</div>
<input type="hidden" className="form-control" name={"base_price["+key+"]"} value={value} />
</div>
)
}
render() {
return(
<div>
{this.renderForm()}
</div>
)
}
}
i try to delete a item which was get in children, but it always removes last element instead. I thought it have some problem with index
I want to delete the particular element, it always deletes the last element from the render list array.
please help me to sort this problem
Try doing this instead.
handleAddNewPrice(){
const { prices } = this.state;
let new_price = {"key": "", "value": ""}
this.setState({ prices: [...prices, new_price] })
}
Edit
and also this:
handleDeletePrice(price_index){
let prices = [...this.state.prices]; //make a seperate copy of state.
prices.splice(price_index, 1);
this.setState({prices: prices});
}
Problem is in your props. The props.index is received once, so if you want to the delete function worked you need use props.index as a state like price. This is sample codes you need to change in the AdditionalPrice Component:
this.state = {
price: this.props.price,
index: this.props.index
}
componentWillReceiveProps(nextProps){
this.setState({
price: nextProps.price,
index: nextProps.index
})
}
handleDeletePrice(){
this.props.handleDeletePrice(this.state.index);
}
i found the problem
my field in child component haven't set the value. see below
<input type="text" className="form-control" placeholder="Key" value={key} onChange={this.handleKeyChange} required/>
thanks all

Fetch data from API when form's search button clicked and show data on another page in React JS

I am developing a React JS web application where I have a form with four select fields (Make, Model, Min price and Max price) and a Search button. The data for search results will be fetched from API according to the selection of options. I want to show that data on another page in a card (page route path: /search) when user clicked on search button. I am using react router. The API url/end point is https://mysterious-journey-51969.herokuapp.com/api/search-vehicle/?q=mercedes&m=sprinter&pf=0&pt=100000 where "q" field matches Vehicle Make, "m" field matches Model, "pf" field matches Min Price, "pt" field matches Max Price. How I can do that?
Here is my Form component code:
import React, { Component } from 'react';
import { Form, FormGroup, Input } from 'reactstrap';
import { veh_data } from '../shared/vehicle_make_and_models';
const defaultValues = [
{ value: 0, text: 0, key: 1 },
{ value: 500, text: 500, key: 2 },
{ value: 1000, text: 1000, key: 3 },
{ value: 1500, text: 1500, key: 4 },
{ value: 2000, text: 2000, key: 5 },
{ value: 2000, text: 2000, key: 6 }
];
const MIN_TITLE = { selected: true, disabled: true, text: 'Min Price' };
const MAX_TITLE = { selected: true, disabled: true, text: 'Max Price' };
class ImgAndForm extends Component {
constructor(props) {
super(props);
this.handleSearch = this.handleSearch.bind(this);
this.keyToOption = this.keyToOption.bind(this);
this.renderOptions = this.renderOptions.bind(this);
this.handleModelChange = this.handleModelChange.bind(this);
this.state = {
minData: [MIN_TITLE, ...defaultValues],
maxData: [MAX_TITLE, ...defaultValues],
minValue: null,
maxValue: null,
modelSelected: null
};
}
renderOptions(data) {
return data.map(datum => {
// this allows us to indicate whether we are selecting or disabling
const selected = datum.selected || false;
const disabled = datum.disabled || false;
return (
<option key={datum.key} value={datum.value} selected={selected} disabled={disabled}>
{datum.text}
</option>
);
});
}
handleModelChange(event) {
console.log(event.target.value);
this.setState({ modelSelected: event.target.value });
}
handleSearch(event) {
alert("Search button clicked");
}
keyToOption(key) {
return key.split("-")
.map(word => word.slice(0, 1).toUpperCase() + word.slice(1))
.join(" ");
}
handleMinSelect = event => {
const value = event.target.value;
const newMaxValues = [];
defaultValues.forEach(datum => {
if (datum.value >= Number.parseInt(value, 10)) {
newMaxValues.push(datum);
}
});
this.setState({
maxData: [MAX_TITLE, ...newMaxValues],
minValue: value
});
};
handleMaxSelect = event => {
const value = event.target.value;
this.setState({ maxValue: value });
};
render() {
const vehicles = veh_data.reduce((acc, veh, i) => {
let make = Object.keys(veh)[0],
vehModels = veh[make];
return {
makes: [
...acc.makes,
<option key={make + i} value={make}>{this.keyToOption(make)}</option>
],
models: {
...acc.models,
[make]: vehModels.map((model, i) => {
return (
<option key={make + model + i} value={model}>
{this.keyToOption(model)}
</option>
);
})
}
};
}, { makes: [], models: [] });
const selectedModels =
this.state.modelSelected && this.state.modelSelected.length ? (
vehicles.models[this.state.modelSelected]
) : (
<option value="">Model (select make first)</option>
);
return (
<div>
<header className="headerbg d-flex">
<div className="container my-auto">
<div className="row">
<div className="offset-1 col-10 offset-lg-0 col-lg-4">
<div id="search-form-div" className="container">
<div className="row">
<div className="col-12 my-4">
<h3>Search</h3>
<Form onSubmit={this.handleSearch}>
<FormGroup>
<Input
onChange={e => this.handleModelChange(e)}
type="select"
name="q"
id="q"
>
<option value="">Make</option>
{vehicles.makes}
</Input>
</FormGroup>
<FormGroup>
<Input type="select" name="m" id="m">
{selectedModels}
</Input>
</FormGroup>
<FormGroup>
<Input type="select"
name="pf"
id="pf"
value={this.state.minValue}
onChange={this.handleMinSelect}>
{this.renderOptions(this.state.minData)}
</Input>
</FormGroup>
<FormGroup>
<Input
type="select"
name="pt"
id="pt"
value={this.state.maxValue}
onChange={this.handleMaxSelect}>
{this.renderOptions(this.state.maxData)}
</Input>
</FormGroup>
<FormGroup>
<Input type="submit" name="search" id="search" className="btn btn-primary" value="Search" />
</FormGroup>
</Form>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
</div>
);
}
}
export default ImgAndForm;
Here is my Search result component code:
import React, { Component } from 'react';
import Smallheader from './SmallHeader';
import { Card, CardImg, CardTitle, CardSubtitle } from 'reactstrap';
class SearchResult extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
<Smallheader />
<div className="my-5">
<div className="container text-center" id="contactContainer">
<div className="row">
<div className="col-lg-12 mx-auto">
<h2 className="text-center">Search Results</h2>
<hr className="my-4 thick-hr" />
</div>
</div>
<div className="row">
<div className="col-6 col-lg-3 mt-4">
<Card>
<a href="#">
<CardImg src="" className="img-fluid" />
<CardTitle>Title Here</CardTitle>
<CardSubtitle>Price Here</CardSubtitle>
</a>
</Card>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default SearchResult;
Here is a working solution...
https://codesandbox.io/s/lrv2w3qxlq?moduleview=1
I've imported your SearchResults component and put it directly below your ImgAndForm, but you can move it anywhere in that render function.
For this specific situation you would need a way to render this on a new 'page' you would need a way to manage shared application state, like Redux or at least a container component as #MikeZinn mentioned, but to do that properly would require as significant amount of work to implement the routing and re-architect your entire program. (If you want I can show you a small hack to produce the same result without that for now, but I'd advise looking into a more permanent solution.)
Since the SearchResults component can be 'stateless' I removed the constructor function, but I left it as a class for now because this component will likely need state eventually.
I added the axios library to fetch the data from the API, but any other XHR module already used in your program will do.
NOTE: Since the specific API endpoints that your form is currently able to query are unavailable, I've hard coded the 'mercedes' example you provided, but the program will log both 'realQuery' and 'dummyQuery' so you see that it is producing the correct query structure for whenever you fix that.
Form Component
import React, { Component } from "react";
import { Form, FormGroup, Input } from "reactstrap";
// import { veh_data } from '../shared/vehicle_make_and_models';
import SearchResult from "./result";
import axios from "axios";
const veh_data = [
{ "alfa-romeo": ["145", "90", "Alfa 6", "Alfasud"] },
{ "aston-martin": ["15", "2-Litre", "AM Vantage", "Atom", "Cygnet", "DB2"] },
{ audi: ["100", "200", "A1", "A2", "A3", "A4", "A5", "A6", "A7"] }
];
const defaultValues = [
{ value: 0, text: 0, key: 1 },
{ value: 500, text: 500, key: 2 },
{ value: 1000, text: 1000, key: 3 },
{ value: 1500, text: 1500, key: 4 },
{ value: 2000, text: 2000, key: 5 },
{ value: 2000, text: 2000, key: 6 }
];
const MIN_TITLE = { selected: true, disabled: true, text: "Min Price" };
const MAX_TITLE = { selected: true, disabled: true, text: "Max Price" };
class ImgAndForm extends Component {
constructor(props) {
super(props);
this.handleSearch = this.handleSearch.bind(this);
this.keyToOption = this.keyToOption.bind(this);
this.renderOptions = this.renderOptions.bind(this);
this.handleModelChange = this.handleModelChange.bind(this);
this.state = {
minData: [MIN_TITLE, ...defaultValues],
maxData: [MAX_TITLE, ...defaultValues],
minValue: "",
maxValue: "",
modelSelected: "",
makeSelected: "",
searchResults: ""
};
}
renderOptions(data) {
return data.map(datum => {
// this allows us to indicate whether we are selecting or disabling
const selected = datum.selected || false;
const disabled = datum.disabled || false;
return (
<option
key={datum.key}
value={datum.value}
selected={selected}
disabled={disabled}
>
{datum.text}
</option>
);
});
}
handleModelChange(event) {
console.log(event.target.value);
this.setState({ modelSelected: event.target.value });
}
handleMakeChange(event) {
console.log(event.target.value);
this.setState({ makeSelected: event.target.value });
}
async handleSearch(event) {
event.preventDefault();
alert("Search button clicked");
let { makeSelected, modelSelected, minValue, maxValue } = this.state;
let realQuery =
"https://mysterious-journey-51969.herokuapp.com/api/search-vehicle/?" +
`q=${makeSelected.split("-").join("")}` +
`&m=${modelSelected.split("-").join("")}` +
`&pf=${minValue}` +
`&pt=${maxValue}`;
let dummyQuery =
"https://mysterious-journey-51969.herokuapp.com/api/search-vehicle/?q=mercedes&m=sprinter&pf=0&pt=100000";
console.log("realQuery (was not run)", realQuery);
console.log("dummyQuery (was run)", dummyQuery);
let res = await axios.get(dummyQuery).catch(err => console.log(err));
console.log("res", res.data);
if (res && res.data) {
this.setState(prevState => {
return {
...prevState,
searchResults: res.data
};
});
}
}
keyToOption(key) {
return key
.split("-")
.map(word => word.slice(0, 1).toUpperCase() + word.slice(1))
.join(" ");
}
handleMinSelect = event => {
const value = event.target.value;
const newMaxValues = [];
defaultValues.forEach(datum => {
if (datum.value >= Number.parseInt(value, 10)) {
newMaxValues.push(datum);
}
});
this.setState({
maxData: [MAX_TITLE, ...newMaxValues],
minValue: value
});
};
handleMaxSelect = event => {
const value = event.target.value;
this.setState({ maxValue: value });
};
render() {
const vehicles = veh_data.reduce(
(acc, veh, i) => {
let make = Object.keys(veh)[0],
vehModels = veh[make];
return {
makes: [
...acc.makes,
<option key={make + i} value={make}>
{this.keyToOption(make)}
</option>
],
models: {
...acc.models,
[make]: vehModels.map((model, i) => {
return (
<option key={make + model + i} value={model}>
{this.keyToOption(model)}
</option>
);
})
}
};
},
{ makes: [], models: [] }
);
const selectedModels =
this.state.makeSelected && this.state.makeSelected.length ? (
vehicles.models[this.state.makeSelected]
) : (
<option value="">Model (select make first)</option>
);
return (
<div>
<header className="headerbg d-flex">
<div className="container my-auto">
<div className="row">
<div className="offset-1 col-10 offset-lg-0 col-lg-4">
<div id="search-form-div" className="container">
<div className="row">
<div className="col-12 my-4">
<h3>Search</h3>
<Form onSubmit={this.handleSearch}>
<FormGroup key={1}>
<Input
onChange={e => this.handleMakeChange(e)}
type="select"
name="q"
id="q"
>
<option value="">Make</option>
{vehicles.makes}
</Input>
</FormGroup>
<FormGroup key={2}>
<Input
onChange={e => this.handleModelChange(e)}
type="select"
name="m"
id="m"
>
{selectedModels}
</Input>
</FormGroup>
<FormGroup key={3}>
<Input
type="select"
name="pf"
id="pf"
value={this.state.minValue}
onChange={this.handleMinSelect}
>
{this.renderOptions(this.state.minData)}
</Input>
</FormGroup>
<FormGroup key={4}>
<Input
type="select"
name="pt"
id="pt"
value={this.state.maxValue}
onChange={this.handleMaxSelect}
>
{this.renderOptions(this.state.maxData)}
</Input>
</FormGroup>
<FormGroup key={5}>
<Input
type="submit"
name="search"
id="search"
className="btn btn-primary"
value="Search"
/>
</FormGroup>
</Form>
<SearchResult results={this.state.searchResults} />
</div>
</div>
</div>
</div>
</div>
</div>
</header>
</div>
);
}
}
export default ImgAndForm;
Results Component
import React, { Component } from "react";
// import Smallheader from './SmallHeader';
import { Card, CardImg, CardTitle, CardSubtitle } from "reactstrap";
class SearchResult extends Component {
renderResults() {
let { results } = this.props;
console.log("results", results);
if (results && results.length) {
return results.map(({ price, text, title, remote_image }, i) => {
return (
<Card key={"card-" + i}>
<a href="#">
<CardImg src={remote_image} className="img-fluid" />
<CardTitle>{title}</CardTitle>
<CardSubtitle>{price}</CardSubtitle>
</a>
</Card>
);
});
}
}
render() {
return (
<div>
{/* <Smallheader /> */}
<div className="my-5">
<div className="container text-center" id="contactContainer">
<div className="row">
<div className="col-lg-12 mx-auto">
<h2 className="text-center">Search Results</h2>
<hr className="my-4 thick-hr" />
</div>
</div>
<div className="row">
<div className="col-6 col-lg-3 mt-4">{this.renderResults()}</div>
</div>
</div>
</div>
</div>
);
}
}
export default SearchResult;
This is exactly the type of problem Redux Solves without using Redux you will need to store the state on a shared parent component. For example,
class Search extends Component {
state = {
searchResult: null,
};
handleSearch = searchResult => {
this.setState({
searchResult,
});
}
render(){
const { searchResult, } = this.state;
if(searchResult === null){
return (
<ImgAndForm handleSearch={this.handleSearch} />
);
}
return (
<SearchResult searchResult={searchResult} />
);
}
}

How to get selected value by default if value match with other value in React Selectbox?

I am updating data from by getting it into form. In form I am getting data from Database. The problem is when I am getting data in selectbox and want to show default selected value if it is match with database field data.
<select disabled ref = {(input)=> this.menu = input} value={this.state.category} onChange={this.handleCat} className="form-control" name="category" data-toggle="tooltip" data-trigger="hover"className="form-control tooltips" title="Select Course Category">
<option disabled>Select Category</option>
{
this.state.categoryData.map((item, index) =>(
<option key={index} value={item._id}>{item.category}</option>
))
}
</select>
You can write value={defaultValue} on the select tag itself:
class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {
options: [
{
value: "Grapefruit",
default: false
},
{
value: "Lime",
default: true
},
{
value: "Coconut",
default: false
},
{
value: "Mango",
default: false
}
]
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.getDefaultValue = this.getDefaultValue.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value);
event.preventDefault();
}
getDefaultValue() {
return this.state.options.filter( ( el ) => {
return el.default == true;
} )[0].value;
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite La Croix flavor:
<select value={this.getDefaultValue()} onChange={this.handleChange}>
{
this.state.options.map( (el, index) => {
return( <Option value={el.value} key={index} /> );
} )
}
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
const Option = ( props ) => (
<option value={props.value}>{props.value}</option>
);
ReactDOM.render(
<FlavorForm />,
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>
<div id="root"></div>
Read more here.

not able to display material-ui dropdown with props values

I am trying to incorporate material-ui DropDown element into my page but I am getting map errors
My page code
import React, {Component} from 'react';
import {Button, Dropdown, Form} from 'semantic-ui-react'
import SimpleReactValidator from 'simple-react-validator';
import cookie from 'react-cookies'
import {Redirect} from 'react-router-dom'
const jsonData = require('../../../../../jsonData/data.json');
const dummyData = require('../../../../../jsonData/dummy.json');
import auth, {
axiosInst as axios,
removeElement,
addElement,
beforeSubmiteShaker,
afterSubmiteShaker
} from "../../../../helper";
import QuestionsFilters from '../../../../components/QuestionsFilters'
import DropDown from '../../../../components/ui/Select/Select'
const items = [
{value: 1, primaryText: 'Dhaval'},
{value: 2, primaryText: 'Dhavalu'},
{value: 3, primaryText: 'Dhavalaa'},
]
class RegisterCandidate extends Component {
constructor(props) {
super(props);
this.state = {
firstname: "",
lastname: "",
mobile_no: "",
email: "",
password: "",
city_id: "",
preference_list: [],
medium: "", //how did u find us
is_looking_for: "",
affiliate: "",
revert: "",
emailExist: "",
mobileExist: "",
isLogin: false,
historyRoute: "",
};
this.validator = new SimpleReactValidator();
}
componentDidMount() {
this.props.fetchCities()
this.props.fetchPreferences()
}
change(e) {
this.setState({
[e.target.name]: e.target.value
})
};
dropDownChange(e, {value, name}) {
this.setState({
[name]: value
})
}
emailcheck(e) {
if (this.validator.fieldValid('email')) {
let uri = '/email/exists';
axios.get(uri, {
params: {email: this.state.email}
})
.then((response) => {
this.setState({emailExist: response.data});
if (response.data.status != 'Failed') {
removeElement("p[id='serv-error email-exist']")
return axios.get('/droppedregistrations/add', {
params: {email: this.state.email}
}).then((response) => {
console.log("Email Dropped " + response.data)
}).catch((error) => {
console.log('failed')
})
} else {
removeElement("p[id='serv-error email-exist']")
addElement("#email", "serv-error email-exist", "This email already exists.")
}
})
.catch(error => {
console.log('error Email')
})
}
}
mobilecheck(e) {
if (this.state.mobile_no != isNaN && this.state.mobile_no.length == 10) {
let uri = '/number/exists';
axios.get(uri, {
params: {mobile_no: this.state.mobile_no}
}).then((response) => {
this.setState({mobile_noExist: response.data});
if (response.data.status != 'Failed') {
removeElement("p[id='serv-error mobile-exist']")
return axios.get('/droppedregistrations/add', {
params: {mobile_no: this.state.mobile_no}
}).then((response) => {
console.log("mobile dropped " + response.data)
}).catch((error) => {
console.log('failed')
})
} else {
removeElement("p[id='serv-error mobile-exist']")
addElement("#mobile_no", "serv-error mobile-exist", "This mobile already exists.")
}
})
.catch(error => {
console.log('You are experiencing slow internet please be patient and try again later')
})
}
}
addUserSubmit(e) {
e.preventDefault();
beforeSubmiteShaker("s_reg_submit", "shaker")
if (this.validator.allValid()) {
const userDetails = {//add data to a donstant to pot
firstname: this.state.firstname,
lastname: this.state.lastname,
email: this.state.email,
password: this.state.password,
mobile_no: this.state.mobile_no,
city_id: this.state.city_id,
medium: this.state.medium,
is_looking_for: this.state.is_looking_for,
preference_list: this.state.preference_list,
affiliate: this.state.affiliate
}
let uri = '/register/candidate';
axios.post(uri, userDetails)
.then((response) => {
this.setState({revert: response.data});
const gotBack = this.state.revert
if (gotBack.status === 'Success') {
cookie.remove('token')
cookie.save('token', gotBack.token, {path: '/'})
if (cookie.load('token')) {
this.setState({isLogin: true})
}
else {
console.log('Something went wrong while redirect.')
}
}
})
.catch(error => {
if (error.response.status === 422) {
afterSubmiteShaker("s_reg_submit", "shaker")
$.each(error.response.data.errors, function (index, value) {
var errorDiv = '#' + index;
$(errorDiv).after("<p id='serv-error' class='validation-message'>" + value + "</p>");
});
}
})
} else {
this.validator.showMessages();
this.forceUpdate();
afterSubmiteShaker("s_reg_submit", "shaker")
}
}
render() {
const {
firstname,
lastname,
mobile_no,
email,
password,
city_id,
preference_list,
medium,
is_looking_for,
affiliate,
isLogin
} = this.state;
//to get the items in level of education
let looking_for = jsonData.looking_for;
var looking_fors = []
for (let i = 0; i < looking_for.length; i++) {
looking_fors.push(looking_for[i]['value']);
}
if (isLogin) {
return <Redirect to='/register/candidate/step2'/>;
} else {
return (
<section className="container mt-3">
{/*one click register section*/}
<div className="row p-3">
<div className="col-md-6">
<div className="card text-center">
<div className="card-body">
<h3>Register Using</h3>
<br/>
<a href="/" className={"btn btn-block btn-lg btn-info"}> Register with Facebook</a>
<a href="/google/redirect" className={"btn btn-block btn-lg btn-danger"}> Register
with Google</a>
<br/>
</div>
</div>
</div>
{/*end of one click register section*/}
{/*manuel register section*/}
<div className="col-md-6">
<div id="shaker" className="card">
<div className="card-body">
<h5 className="card-title">Register Candidate</h5>
<Form onSubmit={this.addUserSubmit.bind(this)}>
<Form.Field>
<label>First Name*</label>
<input name="firstname" id="firstname" value={firstname}
onChange={e => this.change(e)} type="text"
placeholder='Enter First Name*'/>
{this.validator.message('first name', firstname, 'required|alpha')}
</Form.Field>
<Form.Field>
<label>Last Name*</label>
<input name="lastname" id="lastname" value={lastname}
onChange={e => this.change(e)} type="text"
placeholder='Enter Last Name'/>
{this.validator.message('last name', lastname, 'required|alpha')}
</Form.Field>
<Form.Field>
<label>Mobile No*</label>
<input name="mobile_no" id="mobile_no" value={mobile_no}
onBlur={this.mobilecheck.bind(this)} onChange={e => this.change(e)}
type="text" placeholder='Enter mobile_no'/>
{this.validator.message('mobile no.', mobile_no, 'required|phone|min:10|max:10')}
</Form.Field>
<Form.Field>
<label>Email*</label>
<input name="email" id="email" value={email}
onBlur={this.emailcheck.bind(this)} onChange={e => this.change(e)}
type="text" placeholder='Enter Email'/>
{this.validator.message('email', email, 'required|email')}
</Form.Field>
<Form.Field>
<label>Password*</label>
<input name="password" id="password" value={password}
onChange={e => this.change(e)} type="password"
placeholder='Enter Password'/>
{this.validator.message('password', password, 'required|min:6')}
</Form.Field>
<Form.Field>
<label>City*</label>
<Dropdown placeholder='Select City' id="city_id" name="city_id" search
selection options={this.props.city_opt} value={city_id}
onChange={this.dropDownChange.bind(this)}/>
{this.validator.message('city', city_id, 'required|gt:0')}
</Form.Field>
<Form.Field>
<label>Preference*</label>
<Dropdown placeholder='Select Preference' id="preference_list"
name="preference_list" search multiple selection
options={this.props.preference_list_opt} value={preference_list}
onChange={this.dropDownChange.bind(this)}/>
{this.validator.message('preference', preference_list, 'required|max:3', false, {max: 'Maximum 3 preferences allowed'})}
</Form.Field>
<Form.Field>
<label>How did you find us?*</label>
<Dropdown placeholder='Please Select' id="medium" name="medium" search
selection options={jsonData.medium} value={medium}
onChange={this.dropDownChange.bind(this)}/>
{this.validator.message('medium', medium, 'required')}
</Form.Field>
<Form.Field>
<label>What are you looking for?*</label>
<Dropdown placeholder='Please Select' id="is_looking_for"
name="is_looking_for" search selection
options={jsonData.looking_for} value={is_looking_for}
onChange={this.dropDownChange.bind(this)}/>
{this.validator.message('', is_looking_for, 'required|in:' + looking_fors)}
</Form.Field>
<Form.Field>
<label>affiliate Code</label>
<input name="affiliate" value={affiliate} onChange={e => this.change(e)}
type="text" placeholder='Enter preference_list'/>
</Form.Field>
<Button id="s_reg_submit" className={"btn btn-block btn-lg"}
type='submit'>Submit</Button>
</Form>
<QuestionsFilters/>
</div>
</div>
</div>
{/*end of manuel register section*/}
<DropDown items={items}/>
</div>
</section>
)
}
}
}
export default RegisterCandidate;
my DropDown component code
import React, {Component} from 'react';
import DropDownMenu from 'material-ui/DropDownMenu';
import MenuItem from 'material-ui/MenuItem';
const styles = {
customWidth: {
width: 200,
},
};
class DropDownMenuSimpleExample extends Component {
constructor(props) {
super(props);
this.state = {value: 1, items: ['abcd', 'efgh']};
}
handleChange(event, index, value) {
return this.setState({value})
}
render() {
let propItems = this.props.items
return (
<DropDownMenu
value={this.state.value}
onChange={this.handleChange.bind(this)}
style={styles.customWidth}
autoWidth={false}
>
{(propItems !== null || propItems != 'undefined' ) ? (propItems).map((item, index) => <MenuItem key={index} value={1}
primaryText="Custom height"/>) : (this.state.items).map((item, index) =>
<MenuItem key={index} value={1} primaryText="Custom width"/>)}
</DropDownMenu>
);
}
}
export default DropDownMenuSimpleExample
it is telling me that It cannot call map on null and in the first render the value of props shows undefined but then it is defined so not able to get to render the DropDown element properly..
any help will be highly appreciated
Please Note :- with just the state I get the proper dropdown but the issue happens only when I am passing props as data for the dropdown

Categories