React JS状态更改没有't重新渲染组件

React JS state change doesn't re-render the component

本文关键字:组件 新渲染 状态 JS React      更新时间:2023-09-26

我有一个主要组件如下:

render() {
    const language = this.props.language.default.portal;
    return (
        <div>
            <div className="searchLeft noPadding col-xl-2 col-lg-2 col-md-2 col-sm-3 col-xs-5">
                <Price language={language} actionFilters={this.props.actionFilters} allCarsInTheList={this.props.carsToShow}/>
            </div>
            <div className="contentRight noPadding col-xl-10 col-lg-10 col-md-10 col-sm-9 col-xs-7">
                <div className="filterBar">
                    <SmallFilters language={language} filters={this.props.filters} allCarsInTheList={this.props.carsToShow} actionFilters={this.props.actionFilters}/>                       
                </div>
            </div>
        </div>
    );
}

我的价格组成如下:

export default class PriceRangeFilter extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        range: {
            low: _.min(this.props.allCarsInTheList.map (i => i.price)),
            high: _.max(this.props.allCarsInTheList.map (i => i.price)),
            active: false
        }
    };
}
handleFilter(){
    if(this.state.range.active){
        this.props.actionFilters.addPriceRangeFilter(this.state.range);
    }else{
        this.props.actionFilters.removePriceRangeFilter();
    }
}
changeFilter(range) {
    this.setState({range: range}, this.handleFilter);
}
deActivate(event) {
    event.preventDefault();
    let n_range = this.state.range;
    n_range.active = false;
    this.changeFilter(n_range);
}
renderSmall() {
    return (
        <div key={this.props.key} className="filter">
            {this.props.title} <Link to="" onClick={this.deActivate.bind(this)}><FontAwesome name="times" className="portalFaRedIcon"/></Link>
        </div>
    );
}
render(){
    const language = this.props.language;
    if(this.props.recap) return this.renderSmall();
    console.log(this.state.range);
    return (
        <div>
            <div className="priceTitle">{language.price}</div>
            <SliderRange language={language}
                         range={this.state.range}
                         min={_.min(this.props.allCarsInTheList.map (i => i.price))}
                         max={_.max(this.props.allCarsInTheList.map (i => i.price))}
                         step={data.configuration.PRICE_RANGE_STEP}
                         sign="€"
                         type="price"
                         onChange={this.changeFilter.bind(this)} />
        </div>
    );
}
}

我的SmallFilters组件如下:

import PriceFilter from './price';

class filters extends React.Component {
    checkFilter(name, filters){
        return filters.some(f => name == f.name);
    }
    showFilter(filters){
        if(this.checkFilter(filter_names.priceRange, filters)){
            return <PriceFilter recap={this.checkFilter(filter_names.priceRange, filters)} title="Price" allCarsInTheList={this.props.allCarsInTheList} actionFilters={this.props.actionFilters}/>
        }
    }
    render(){
        const language = this.props.language;
        const filters = this.props.filters;
        return (
            <div className="filters noPadding col-xl-8 col-lg-6 col-md-6 col-sm-5 col-xs-12">
                <ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500} transitionEnterTimeout={500} transitionLeaveTimeout={500}>
                    {this.showFilter(filters)}
                </ReactCSSTransitionGroup>
            </div>
        );
    }
}

问题出在SmallFilters组件中。我在那里包括了与搜索组件相同的价格组件。然后,在价格组件中,如果this.props.recap为真,则返回renderSmall函数。

当我点击renderSmall内部的链接以停用过滤器时,它应该会更新状态。但这个州并没有改变。CCD_ 4保持为真。

有什么建议吗?

更新

SliderRange组件代码如下:

import React, {PropTypes} from 'react';
import {formatNumber} from './formatNumber';
export default class SliderRange extends React.Component {
    constructor(props) {
        super(props);
        this.state = this.getStateFromProps(this.props);
    }
    componentWillReceiveProps(newProps){
        this.setState(this.getStateFromProps(newProps));
    }
    getStateFromProps(props) {
        return {
            low: props.range.low,
            high: props.range.high,
            active: props.range.active
        };
    }
    numberWithSpace(number) {
        return (this.props.type == "year") ? number : formatNumber(number);
    }

    handleChange(low, high, active) {
        let n_active = active;
        if(low!=this.state.low) n_active = true;
        if(high!=this.state.high) n_active = true;
        if(low == this.props.min && high == this.props.max) n_active = false;
        const result = {
            low: low,
            high: high,
            active: n_active
        };
        this.props.onChange(result);
    }
    handleActive(event) {
        const checkbox = event.target.checked;
        let low = this.state.low;
        let high = this.state.high;
        if(checkbox && this.state.low == this.props.min && this.state.high == this.props.max) {
            low = this.props.min + this.props.step;
            high = this.props.max - this.props.step;
        }else{
            low = this.props.min;
            high = this.props.max;
        }
        this.handleChange(low, high, checkbox);
    }
    handleLow(event) {
        if(parseInt(event.target.value) < parseInt(this.state.high)){
            this.handleChange(event.target.value, this.state.high, this.state.active);
        }
    }
    handleHigh(event) {
        if(parseInt(event.target.value) > parseInt(this.state.low)) {
            this.handleChange(this.state.low, event.target.value, this.state.active);
        }
    }
    render() {
        const sign = this.props.sign;
        const min = this.props.min;
        const max = this.props.max;
        const step = this.props.step;

        const low = this.state.low;
        const high = this.state.high;
        const active = this.state.active;
        return (
            <div>
                <div className="rangeValues">Range : {this.numberWithSpace(low)} {sign} - {this.numberWithSpace(high)} {sign}</div>
                <section className="range-slider">
                    <input type="checkbox" checked={active} onChange={this.handleActive.bind(this)}/>
                    <input type="range" name="first" value={low} min={min} max={max} step={step}  onChange={this.handleLow.bind(this)} className="firstRange"/>
                    <input type="range" name="second" value={high} min={min} max={max} step={step} onChange={this.handleHigh.bind(this)} className="secondRange"/>
                    <div className="minValue">{this.numberWithSpace(min)} {sign}</div>
                    <div className="maxValue">{this.numberWithSpace(max)} {sign}</div>
                </section>
            </div>
        );
    }
}
SliderRange.propTypes = {
    language: PropTypes.object.isRequired,
    range: PropTypes.object.isRequired,
    min: PropTypes.number.isRequired,
    max: PropTypes.number.isRequired,
    step: PropTypes.number.isRequired,
    onChange: PropTypes.func.isRequired
};

您正在更改嵌套属性。尝试使用object.assign((创建一个新对象,如下所示:

deActivate(event) {
    event.preventDefault();
    let n_range = Object.assign({}, this.state.range);
    n_range.active = false;
    this.changeFilter(n_range);
}