反应:道具更改时不会触发componentWillReceiveProps

时间:2018-07-05 07:59:17

标签: reactjs

我是新来的反应者,它的生命周期是这样,所以当前正在学习一些教程,我陷入了一个问题,即componentWillReceiveProps生命周期方法无法按我期望的方式工作。 事实是,在 App 组件中,我正在将prop isActive传递给 Card 组件,并且当输入复选框处于选中状态/未选中状态时,它正在更改其值,因此我希望componentWillReceiveProps生命周期要触发的方法。但是,这根本不起作用。在这种情况下,您有什么可以建议的?我也愿意寻求最佳实践建议。谢谢您的宝贵时间。

组件代码:

//App.js
import React, {Component} from 'react';
import Ticker from "./Ticker/Ticker";
import currencies from './currencies';
import Card from "./Card/Card";
import uuid from "uuid";
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';

class App extends Component {

    state = {
        activePairs: []
    };

    handleCheckbox = (rateId, event) => {

        const {checked} = event.target;

        this.setState(({activePairs}) => {

            let pairs = [...activePairs];

            if (checked) {
                if (!pairs.includes(rateId)) {
                    pairs.push(rateId);
                }
            } else {
                let index = pairs.findIndex(rate => rate === rateId);
                pairs.splice(index, 1);
            }

            return {
                activePairs: pairs
            };
        });
    };

    render() {

        return (
            <div className="App">
                <Ticker handleCheckbox={this.handleCheckbox.bind(this)}/>

                <div className="container">
                    <div className="row">
                        {currencies.map(pair => <Card key={"card-" + uuid.v4()} currency={pair}
                                                      isActive={this.state.activePairs.includes(pair)}/>)}
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

//Card.js
import React, {Component} from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import '../App.css';

class Card extends Component {

    state = {
      value: 0
    };

    componentWillReceiveProps(nextProp) {
        console.log(nextProp);

        if (!this.props.isActive && nextProp.isActive) {
            this.updateExchangeRate();
            this.interval = setInterval(this.updateExchangeRate, 3000);
        } else if (this.props.isActive && !nextProp.isActive) {
            clearInterval(this.interval);
            this.setState({
                value: 0
            })
        }
    }

    updateExchangeRate = () => {
        return fetch(`https://www.cbr-xml-daily.ru/daily_json.js`).then(r => r.json()).then(res => {

            let exRate = res["Valute"][this.props.currency.toUpperCase()]['Value'] + (Math.random() * (0.99 - 0.01 + 1) + 0.01);
            let maximum = exRate + 5.00;
            let minimum = exRate - 5.00;

            this.setState({
                value: (Math.floor(Math.random() * (maximum - minimum + 1)) + minimum).toFixed(2)
            });
        });
    };

    render() {
        return (
            <div className="col-md-3 col-sm-6 mb-3">
                <div className="card text-center text-white bg-info">
                    <div className="card-header bg-info">{this.props.currency.toUpperCase() + " to RUB"}</div>
                    <div className="card-body">
                        <h5 className="card-title">Current exchange pair:</h5>
                        <p className="card-text">{this.state.value}</p>
                    </div>
                </div>
            </div>
        );
    }
}

export default Card;

//Ticker.js
import React, {Component} from 'react';
import currencies from "../currencies";

export default class Ticker extends Component {

    state = {
        currencies: currencies
    };

    render() {
        return (
            <div id="wrapper">
                <div id="sidebar-wrapper">
                    <ul id="sidebar-ul" className="sidebar-nav">
                        {this.state.currencies.map(currency => {
                            return <li key={currency}>
                                <input id={currency + "-input"} type="checkbox" onChange=
                                    {
                                        this.props.handleCheckbox.bind(this, currency)
                                    }/>
                                <label htmlFor={currency + "-input"} className="text-info"
                                       role="button"> {currency.toUpperCase()} rate</label>
                            </li>
                        })}
                    </ul>
                </div>
            </div>
        );
    }
}

//currencies.js
export default ["aud", "azn", "gbp", "bgn", "usd", "eur"];

1 个答案:

答案 0 :(得分:1)

好吧,我终于在这里找到了引起问题的原因。在App组件中,我将uuid模块用作每个Card组件的关键道具,因此,每次isActive道具进行更新时,它总是渲染一个新的Card组件。

解决方案:使用常量ID代替它作为关键道具。