簡體   English   中英

React JS狀態更改不會重新渲染組件

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

我有一個主要組成部分,如下所示:

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為true,則在價格組件中返回renderSmall函數。

當我單擊renderSmall內部的鏈接以停用過濾器時,它應該更新狀態。 但是狀態沒有改變。 this.state.range.active保持為true。

有什么建議嗎?

更新

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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM