I am looping through an array in react using map function to return option tags for HTML select tag. But it does not seem to work. Project_titles array is properly populated with data.
I have used same code in some other place and it is working there.
render() {
<select
id="sel4"
onChange={event => this.setState({ project: event.target.value })}
>
{this.func()}
</select>;
}
func() {
this.state.project_titles.map(function(title, i) {
return (
<option key={i} value={title}>
{title}
</option>
);
});
}
Select tag should get populated with options but it is empty.
This works. The issue with your code is you are not returning the final Options array from you func() function.
render(){
<select
id="sel4"
onChange={event => this.setState({ project: event.target.value })}
>
{this.func()}
</select>;
};
func = () => {
return this.state.project_titles.map(function(title, i) {
return (
<option key={i} value={title}>
{title}
</option>
);
});
};
Related
Essentially I have a select dropdown that is being populated by an API.
If you look at the following code snippet, I essentially created an array of IDs called "first" and made it the value for the first select option above the map that I've done to populate the rest of the select.
Now in my handleChange when I log the value of a selected option it returns the value of the given option in an array of string numbers.
--> Example... if user selects the second option ['1']
When the user selects 'All IDs' that's where the issue is. When that option is selected whats logged is ---> ['1,2,6,8,15,16,17,20,22,23,24,25,26,27,30,32,33,34,36']
I understand that I could use the split method but it crashes for any other option that's selected.
How could I get around that?
const DropDown = ({ list = [], title, onChange }) => {
const handleChange = (e) => {
const { value } = e.target
const arr = [value]
console.log(arr)
// onChange(Number(value))
}
const first = list.map((list) => list.id)
return (
<>
<select onChange={handleChange}>
<option value={first}>{title}</option>
{list.map((item) => (
<option key={item.id} value={item.id}>
{item.name}
</option>
))}
</select>
</>
)
}
e.target.value is a string, so you'll need to change this:
const arr = [value]
to
const arr = value.split(",").map(Number);
You can use whatever you want as the value (key) of the "All" option. For example, in the following, I've used "all" as the key and handled that specifically in the handleChange handler.
const DropDown = ({ list = [], title, onChange }) => {
const handleChange = (e) => {
const { value } = e.target;
if (value === "all") {
onChange(list.map((l) => l.id));
} else {
onChange([parseInt(value, 10)]);
}
};
return (
<>
<select onChange={handleChange}>
<option value="all">{title}</option>
{list.map((item) => (
<option key={item.id} value={item.id}>
{item.name}
</option>
))}
</select>
</>
);
};
You can use value.split(",") as well, which would work for your specific example but would not be sufficient if you need to handle different types of items in the list (perhaps strings that could contain their own ,s).
Here's the above code in action
import React from 'react'
export default function CurrencyRow(props) {
const {
currencyOptions
} = props
return (
<div>
<input type="number" className="input-box" />
<select>
{currencyOptions.map(option => (
<option key={option} value={option}>{option}</option>
))}
</select>
</div>
)
}
The key must always be unique for each element and Since the key is repeating in the array currencyOptions the errors shows up.
To avoid this error you can try it this way
array.map((element, index) => { /* ... */ })
You can read more about it at : Mozilla Docs
since the index is unique for each element you can use
currencyOptions.map(option,index => (
<option key={index} value={option}>{option}</option>
))
I'd like to know how to get the object properties from a json.
I got this fake API:
{
"Arreglo":[
{ "label": "Choose Wisely", "value": "Choose Wisely"},
{ "label": "Primer opción", "value": "1", "testvariable": [] },
{ "label": "Segunda opción"," value": "2" },
{ "label": "Tercer opción", "value": "3" }
]
}
This is my App.js :
import SelectComponent from './Components/SelectComponent';
import {Arreglo} from './FakeApis/SelectOptions';
function App() {
return (
<div className="App">
<SelectComponent items1 = {Arreglo}/>
</div>
);
}
And this is my form and how I set the state:
export default function SelectComponent(items1) {
console.log(items1.items1);
const[testVar, testFunction] = useState(false);
const [items] = React.useState(items1.items1);
<form>
<select onChange = {handleChange}>
{items.map(item => (
<option
key={item.value}
value={item.value}
label={item.label}
>
{item.label}
</option>
))}
</select>
</form>
In this function I'd like to know how to get the "testvariable"
const handleChange = event => {
console.log("The variable --->");
};
Hope I explained myself good.
regards!
Since your data doesn't have any unique identifying id, you can use the index of each item in the array as a reference point that you can use in your change handler.
To do this, first read your data into some piece of state. While your data is static now, this is good practice for when you start speaking to an actual API to fetch data.
Once you have that data available within your component (you can abstract this back into a separate Select Component, I just did it one file for ease of understanding), you can access the selected option by using the selectedIndex property of the event within the change event handler.
import {Arreglo} from './FakeApis/SelectOptions';
export default function App() {
// Read the data into state
const [data] = React.useState(Arreglo);
const handleChange = e => {
// The index of the selected option
const { selectedIndex } = e.currentTarget;
// Grab the element at that index
const selectedOption = data[selectedIndex];
// You can now access any property on that element, like testVariable
console.log(selectedOption.testvariable);
};
return (
<div className="App">
<select onChange={handleChange}>
{data.map(item => (
<option key={item.value} value={item.value} label={item.label}>
{item.label}
</option>
))}
</select>
</div>
);
}
To access the testVar your handleChange function must be inside the SelectComponent function just like the testVar:
export default function SelectComponent(items1) {
const[testVar, testFunction] = useState(false);
const [items] = React.useState(items1.items1);
const handleChange = event => {
// testVar can be called here
}
<form>
<select onChange = {handleChange}>
{items.map(item => (
<option
key={item.value}
value={item.value}
label={item.label}
>
{item.label}
</option>
))}
</select>
</form>
Something that you could do in order to solve your issue and have access to your data is to replace your select tag by the following:
<select onChange = {(event) => handleChange(event, items)}>
{items.map(item => (
<option
key={item.value}
value={item.value}
label={item.label}
>
{item.label}
</option>
))}
</select>
And let your handleChange function accept another parameter:
const handleChange = (event, items) => {
// items is now available in this block and you can get testvariable here.
console.log(`The variable ${items}`);
};
Its suppose return component that realize dropdown list by getting array of strings. Its probably some mistake how use elements of array.
import React from 'react'
class DropDownList extends React.Component {
renderDropDownList = () => {
const { dropDownDownData } = this.props
return (
<div className="book-shelf-changer">
<select>
dropDownDownData.map(function(item){
<option key = {item} value={item}>{item}</option>
})
</select>
</div>
)
}
render() {
const optionList = ['Move to...','Currently Reading','Want to Read','Read','None']
return this.renderDropDownList(optionList)
}
}
export { DropDownList }
I think it's just because you have forgotten some curly braces to call dropDownData function and your function is not interpreted as Javascript function. Add a return to your map function too.
It should work with this :
<select>
{dropDownDownData.map(function(item){
return (<option key = {item} value={item}>{item}</option>);
})}
</select>
You can also use ES6 syntax for your map expression :
<select>
{dropDownDownData.map(item => (<option key = {item} value={item}>{item}</option>))}
</select>
This is my react functional component, I am sending inputs as props which are to be displayed and then looping through the inputs to check which inputs are to be displayed according to condition. This is my component :-
const TopInputComponent = (props) => {
const inputs = props.inputs;
inputs.map((input,index)=>{
if(input.type == "textInput"){
return (<Textfield key={index}
onKeyDown={(event)=>{
if(event.key == "Enter"){
onFilterSelected({'min_price':parseInt(event.target.value)});
}
}}
label={input.placeholder}
floatingLabel
/> )
}else if(input.type == "selectInput"){
return (<div key={index}>
<label>{input.placeholder}</label>
<select >
<option value="1">1</option>
<option value="2">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>)
}
})
}
I am getting this Error :
"A valid React element (or null) must be returned. You may have
returned undefined, an array or some other invalid object."
There are two, three, possibly four problems:
You aren't returning anything out of the function, because you haven't returned the result of map.
A React component must return a single element or null, it can't return an array.
Within your map callback, you're only returning something if input.type is "textInput" or "selectInput", not if it's something else. That will leave undefined values in your resulting array. If those are the only two possible values, change else if(input.type == "selectInput"){ to just } else {. If not, handle the other cases.
floatingLabel in the Textfield's start tag seems odd, it will be a freestanding boolean attribute.
So you'll probably want to wrap those elements in something, perhaps a div (see *** lines):
const TopInputComponent = (props) => {
const inputs = props.inputs;
return <div>{inputs.map((input,index)=>{ // ***
if(input.type == "textInput"){
return (<Textfield key={index}
onKeyDown={(event)=>{
if(event.key == "Enter"){
onFilterSelected({'min_price':parseInt(event.target.value)});
}
}}
label={input.placeholder}
floatingLabel
/> )
} else { // *** Removed: if(input.type == "selectInput"){
return (<div key={index}>
<label>{input.placeholder}</label>
<select >
<option value="1">1</option>
<option value="2">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>)
}
})}</div>; // ***
}
Simplified live example:
const MyComponent = props => {
const {inputs} = props;
return <div>
{inputs.map((input, index) => <input key={index} type={input.type} name={input.name} value={input.value || ''} />)}
</div>;
};
ReactDOM.render(
<MyComponent inputs={[
{type: "text", name: "one"},
{type: "button", name: "btn", value: "Click me"}
]} />,
document.getElementById("react")
);
<div id="react"></div>
<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>
Inside map you are returning the elements, that elements will group into an array by map (returns an array), You need to return the result of map also. You are returning an array but react component can't return an array, so wrap the map result inside a div.
Use this:
const TopInputComponent = (props) => {
const inputs = props.inputs;
return <div> { inputs.map((input,index)=>{ //added return
....
One more issue is, inside map if you don't return anything by default it will return undefined, you are using two condition, may be possible if none of them is true, in that case undefined will be returned. So always use a default case also, use it in this way:
return a.map(el => {
if(/*condition 1*/)
return //1;
else if(/*condition 2*/)
return //2;
else
return //3;
})
Check this example:
a = [1,2,3,4,5,6];
function withoutReturn () { a.map(i => i); };
function withReturn () { return a.map(i => i); };
console.log('withoutReturn', withoutReturn());
console.log('withReturn', withReturn())