在componentDidMount()中更新redux状态下的下拉菜单。

问题描述 投票:0回答:1

我是一个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
);

enter image description here

javascript reactjs redux react-redux
1个回答
1
投票

在这种情况下,最好使用 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。

© www.soinside.com 2019 - 2024. All rights reserved.