问题
How to render options inside select tag in ReactJs?
I have a json data for country and state. I want to render states in select tag dynamically with selected country.
const onCountryChange = value => {
const country = value.split("_")[0];
const countryCode = value.split("_")[1];
const countryId = value.split("_")[2];
setCountry(country);
setCountryCode(countryCode);
setCountryId(countryId)
};
Select tag for country
<select value={country} onChange={e => onCountryChange(e.target.value)}>
<option value="" disabled>Select Country</option>
{
COUNTRIES.map((country, index) => {
return (
<option
key={index}
value={country.name + "_+" + country.phoneCode + "_" + country.id}
>
{country.name}
</option>
);
})
}
</select>
Select tag for state
<select value={state} onChange={e => onStateChange(e.target.value)} >
<option value="" disabled>Select State/Province</option>
{
STATES.filter(states => (states.country_id === countryId)).map((state, index) => {
console.log(state.name)
return (
<option
key={index}
value={state.name + "_+" + state.id}
>
{state.name}
</option>
);
})
}
</select>
Drop down for country is rendering correctly. When I select a country, corresponding states are not rendering in select tag where as states are displayed in console.
回答1:
Without seeing more of your code I can't answer your question exactly, but I have provided a basic working snippet that uses a simple re-usable Select
component and stores the ids of the selected country and state using useState
.
Also, there are some significant inefficiencies in your code that if you address will make everything more readable and may help avoid or more easily find errors in behavior or output.
Firstly, you have a great deal of duplication in writing two separate select
elements which you have further complicated by returning from within them. This is a great time to abstract to a separate component.
function Select({ options, value, title, handleSelectChange }) {
return (
<select name="title" value={value ? value : ''} onChange={handleSelectChange} >
<option value="" disabled selected hidden>{title}</option>
{options.map(option =>
<option key={option.id} value={option.id} >
{option.name}
</option>
)}
</select>
)
}
Next, you are declaring an anonymous function in onChange
to call a named function and only passing the event
. Named functions in React can be called by direct reference and they will be passed the event intrinsically so you could simplify you code thus:
const onCountryChange = (event) => {
console.log(event.target.value);
...
}
<select ... onChange={onCountryChange}>
Within onCountryChange
there is again a lot of duplication (and three calls to split
the same string). You can use destructuring assignment to simplify this
const onCountryChange = (e) => {
const [country, countryCode, countryId] = e.target.value.split("_");
}
These are small pointers, but learning the basics and coding as cleanly as possible will help avoid tangles.
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script 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.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
const { useState} = React;
const countries = [
{ id: 'AD', name: 'Andorra' },
{ id: 'AE', name: 'United Arab Emirates' },
{ id: 'AF', name: 'Afghanistan' },
{ id: 'AG', name: 'Antigua and Barbuda' },
{ id: 'AI', name: 'Anguilla' },
]
const states = [
{ id: 'ad1', name: 'AD: State 1', countryId: 'AD' },
{ id: 'ad2', name: 'AD: State 2', countryId: 'AD' },
{ id: 'ad3', name: 'AD: State 3', countryId: 'AD' },
{ id: 'st1', name: 'AI: State 4', countryId: 'AI' },
{ id: 'st2', name: 'AI: State 5', countryId: 'AI' },
{ id: 'st3', name: 'AI: State 6', countryId: 'AI' },
{ id: 'ag1', name: 'AG: State 7', countryId: 'AG' },
{ id: 'ag2', name: 'AG: State 8', countryId: 'AG' },
{ id: 'ag3', name: 'AG: State 9', countryId: 'AG' },
{ id: 'af1', name: 'AF: State 10', countryId: 'AF' },
{ id: 'af2', name: 'AF: State 11', countryId: 'AF' },
{ id: 'af3', name: 'AF: State 12', countryId: 'AF' },
{ id: 'ae1', name: 'AE: State 13', countryId: 'AE' },
{ id: 'ae2', name: 'AE: State 14', countryId: 'AE' },
{ id: 'ae3', name: 'AE: State 35', countryId: 'AE' }
]
function Select({ options, value, title, handleSelectChange }) {
return (
<select name="title" value={value ? value : ''} onChange={handleSelectChange} >
<option value="" disabled selected hidden>{title}</option>
{options.map(option =>
<option key={option.id} value={option.id} >
{option.name}
</option>
)}
</select>
)
}
function App() {
const [selectedCountryId, setSelectedCountryId] = useState(null);
const [selectedStateId, setSelectedStateId] = useState(null);
const handleCountryChange = (e) => {
setSelectedStateId(null);
setSelectedCountryId(e.target.value);
}
const handleStateChange = (e) => {
setSelectedStateId(e.target.value);
}
return (
<div>
<div className="select-container">
<Select
options={countries}
value={selectedCountryId}
title='Select Country'
handleSelectChange={handleCountryChange}
/>
<Select
options={states.filter(state =>
state.countryId === selectedCountryId)}
value={selectedStateId}
title='Select State/Province'
handleSelectChange={handleStateChange}
/>
</div>
<div class='output'>
<p>Selected Country Id: {selectedCountryId}</p>
<p>Selected State Id: {selectedStateId}</p>
</div>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('App'));
</script>
来源:https://stackoverflow.com/questions/63834854/dynamic-drop-down-for-country-state-in-reactjs