基本上,我想使用react+react bootstrap创建动态选择下拉列表/选择。这就像国家、州和城市。
根据我当前的代码,基于setSelectedCountry,我也想更新setStates。我想根据所选国家更新各州列表。
总共有6个状态可用,其中3个用于管理列表,3个用于选择的管理状态。
我怎样才能做到这一点?请帮帮我。
App.js
import { useEffect, useState } from 'react';
import RBContainer from './components/RBComponents/container/RBContainer'
import RBSelect from './components/RBComponents/select/RBSelect'
import data from './db.json';
import './App.scss';
function App() {
const [countries, setCountries] = useState([])
const [states, setStates] = useState([])
const [cities, setCities] = useState([])
const [selectedCountry, setSelectedCountry] = useState("Select Country")
const [selectedState, setSelectedState] = useState("Select State")
const [selectedCity, setSelectedCity] = useState("Select City")
// initial set country select menu items
useEffect(() => {
setCountries(data)
}, [])
const onCountryChangeHandler = (e) => {
console.log(e.target.value);
setSelectedCountry(e.target.value)
// setSelectedCountry((prv) => prv, e.target.value);
onSelectCountry(e)
}
// setState as callback
function onSelectCountry(e) {
console.log('working...')
countries.forEach(element => {
if (element.countryId === parseInt(e.target.value)) {
setStates((prv) => prv, element.states)
}
console.log(states);
});
}
const onStateChangeHandler = (e) => {
console.log(e.target.value);
}
return (
<div className='app my-4'>
<RBContainer>
<RBSelect className='mb-4' value={selectedCountry} onChange={onCountryChangeHandler}>
<option disabled>Select Country</option>
{countries.map(country => (
<option
key={country.countryId}
value={country.countryId}
>
{country.countryName}
</option>
))}
</RBSelect>
<RBSelect value={selectedState} onChange={onStateChangeHandler}>
<option disabled>Select State</option>
{states.map(state => (
<option
key={state.stateId}
value={state.stateId}
>
{state.stateName}
</option>
))}
</RBSelect>
</RBContainer>
</div>
);
}
export default App;
这是我的本地json文件。
db.json
[
{
"countryId": 1,
"countryName": "India",
"states": [
{
"stateId": 1,
"stateName": "Gujarat",
"cities": [
{
"cityId": 1,
"cityName": "Ahmadabad"
},
{
"cityId": 2,
"cityName": "Surat"
},
{
"cityId": 2,
"cityName": "Baroda"
}
]
},
{
"stateId": 2,
"stateName": "Maharashtra",
"cities": [
{
"cityId": 3,
"cityName": "Mumbai"
},
{
"cityId": 4,
"cityName": "Pune"
}
]
}
]
},
{
"countryId": 2,
"countryName": "USA",
"states": [
{
"stateId": 3,
"stateName": "California",
"cities": [
{
"cityId": 5,
"cityName": "Los Angeles"
},
{
"cityId": 6,
"cityName": "San Diego"
}
]
}
]
}
]
将国家/州等的实际列表保持在react状态不是一个好主意。没有必要,它们是不变的。您只需要存储选定的项,然后就可以从函数中的JSON派生实际列表,而不必将它们存储在新状态中。
您可能需要退一步进行重构。
import { useEffect, useState } from 'react';
import RBContainer from './components/RBComponents/container/RBContainer'
import RBSelect from './components/RBComponents/select/RBSelect'
import data from './db.json';
import './App.scss';
function App() {
const [selectedCountry, setSelectedCountry] = useState("Select Country");
const [selectedState, setSelectedState] = useState("Select State");
const [selectedCity, setSelectedCity] = useState("Select City");
const onCountryChangeHandler = (e) => {
setSelectedCountry(e.target.value);
};
const onStateChangeHandler = (e) => {
setSelectedState(e.target.value);
};
const onCityChangeHandler = (e) => {
setSelectedCity(e.target.value);
};
const country = data.find(
(country) => country.countryId === parseInt(selectedCountry)
);
const state = country?.states?.find(
(state) => state.stateId === parseInt(selectedState)
);
return (
<div className="app my-4">
<RBContainer>
<RBSelect
className="mb-4"
value={selectedCountry}
onChange={onCountryChangeHandler}
>
<option disabled>Select Country</option>
{data.map((country) => (
<option key={country.countryId} value={country.countryId}>
{country.countryName}
</option>
))}
</RBSelect>
<RBSelect value={selectedState} onChange={onStateChangeHandler}>
<option disabled>Select State</option>
{country?.states.map((state) => (
<option key={state.stateId} value={state.stateId}>
{state.stateName}
</option>
))}
</RBSelect>
<RBSelect value={selectedCity} onChange={onCityChangeHandler}>
<option disabled>Select City</option>
{state?.cities.map((city) => (
<option key={city.cityId} value={city.cityId}>
{city.cityName}
</option>
))}
</RBSelect>
</RBContainer>
</div>
);
}
export default App;