我是一个react-redux的初学者。我在react组件中实现了依赖性下拉功能(Country => State => City)。
我想在收到redux状态的数据时更新下拉菜单的值。
我正在从redux状态中获取 this.props.dropdownForm
并据此 changeCountry
, changeState
, changeCity
函数,其中我根据条件来设置所选国家。
我所面临的问题是这段代码无法工作。
componentDidMount() {
if (this.props.dropdownForm) {
this.changeCountry();
this.changeState();
// this.changeCity();
}
}
但当我把上面的代码放在setTimeout中时,它就会更新国家下拉菜单。
componentDidMount() {
setTimeout(() => {
if (this.props.dropdownForm) {
this.changeCountry();
this.changeState();
// this.changeCity();
}
}, 100);
}
但这也是不一致的,也就是说有时能用,有时不能用。
没有得到这种奇怪的行为。
下面是我的代码。
import React from 'react';
import { connect } from 'react-redux';
import { Col, FormGroup, Label, Input } from 'reactstrap';
import { createStructuredSelector } from 'reselect';
import { getDropdownData } from '../../redux/profile/profile.selectors';
class Dropdown extends React.Component {
constructor(props) {
super(props);
this.state = {
countries: [
{ name: 'Germany', states: [{ name: 'A', cities: ['Duesseldorf', 'Leinfelden-Echterdingen', 'Eschborn'] }] },
{ name: 'Spain', states: [{ name: 'B', cities: ['Barcelona'] }] },
{ name: 'USA', states: [{ name: 'C', cities: ['Downers Grove'] }] },
{ name: 'Mexico', states: [{ name: 'D', cities: ['Puebla'] }] },
]
};
this.changeCountry = this.changeCountry.bind(this);
this.changeState = this.changeState.bind(this);
this.changeCity = this.changeCity.bind(this);
}
componentDidMount() {
if (this.props.dropdownForm) {
this.changeCountry();
// this.changeState();
// this.changeCity();
}
}
changeCountry(event) {
let countryVal = !event && this.props.dropdownForm ? this.props.dropdownForm.country : event.target.value;
this.setState({ selectedCountry: countryVal });
const result = this.state.countries.find(cntry => {
return cntry.name === countryVal
});
result ? this.setState({ states: result.states }) : this.setState({ states: null });
this.setState({ cities: null });
}
changeState(event) {
let stateVal = !event && this.props.statePropSelected ? this.props.statePropSelected : event.target.value;
this.setState({ selectedState: stateVal });
const stats = this.state.countries.find(cntry => {
return cntry.name === this.state.selectedCountry
}).states;
const result = stats.find(stat => stat.name === stateVal);
result ? this.setState({ cities: result.cities }) : this.setState({ cities: null });
}
changeCity(e) {
this.props.onChangeCity(e);
}
render() {
let country = this.state.selectedCountry;
let state = this.state.selectedState;
return (
<>
<FormGroup row>
<Col md="4">
<Label htmlFor={this.props.countryProp} className="required">{this.props.countryProp}</Label>
</Col>
<Col xs="12" md="8">
<Input type="select" name="country" id={this.props.countryProp} placeholder={this.props.countryProp} value={country} onChange={this.changeCountry}>
<option>Select Country</option>
{this.state.countries.map((e, key) => {
return <option key={key}>{e.name}</option>;
})}
</Input>
</Col>
</FormGroup>
<FormGroup row>
<Col md="4">
<Label htmlFor={this.props.stateProp} className="required">{this.props.stateProp}</Label>
</Col>
<Col xs="12" md="8">
<Input type="select" name="state" id={this.props.stateProp} placeholder={this.props.stateProp} value={state} onChange={this.changeState}>
<option>Select State</option>
{
this.state.states ? this.state.states.map((e, key) => {
return <option key={key}>{e.name}</option>;
}) : null
}
</Input>
</Col>
</FormGroup>
<FormGroup row>
<Col md="4">
<Label htmlFor={this.props.cityProp} className="required">{this.props.cityProp}</Label>
</Col>
<Col xs="12" md="8">
<Input type="select" name="city" id={this.props.cityProp} placeholder={this.props.cityProp} onChange={this.changeCity}>
<option>Select City</option>
{
this.state.cities ? this.state.cities.map((e, key) => {
return <option key={key}>{e}</option>;
}) : null
}
</Input>
</Col>
</FormGroup>
</>
)
}
}
const mapStateToProps = createStructuredSelector({
dropdownForm: getDropdownData
});
export default connect(mapStateToProps)(Dropdown);
选择器:
import { createSelector } from 'reselect';
const dropdown = (state) => {
return state.profile.items.personal_details;
};
export const getDropdownData = createSelector(
[dropdown],
(data) => data
);
在这种情况下,最好使用 componentDidUpdate 而不是 componentDidMount。由于你正在寻找一个特定属性的更新,这是一个不错的选择。
componentDidMount() {
if (this.props.dropdownForm) {
this.changeCountry();
// this.changeState();
// this.changeCity();
}
}
改成这样
componentDidUpdate() {
if (this.props.dropdownForm && !this.state.countriesChanged) {
this.changeCountry();
this.setState({ countriesChanged: true });
// this.changeState();
// this.changeCity();
}
}
编辑注释:
你可以在状态中添加一个名为 "countryUpdated "的字段 作为一个标志,并在执行该块时将其设置为true。