繁体   English   中英

React 组件道具的更改是否会导致重新渲染?

[英]Does a change in a React components props cause a re-render?

我正在构建一个简单的计时器作为 React 实践。 现在我只专注于让几秒钟工作。 当用户在baseSeconds输入选择时,计时器将在该秒停止。

如果您将数字硬编码为道具而不是传递状态,它就会起作用。 并且我知道基于我作为测试输出的{this.props.baseSeconds}组件中的道具正在发生变化。 但是当我把this.state.baseSeconds作为道具时,计时器会继续运行。

设置的父组件:

const baseMin = [];
for (var i=0; i <= 60; i++) {
    baseMin.push(i);
}

const baseSec = [];
for (var i=0; i <= 60; i++) {
    baseSec.push(i);
}

const displayMinutes = baseMin.map((minute) => 
    <option value={minute}>{minute}</option> 
)

const displaySeconds = baseSec.map((second) => 
    <option value={second}>{second}</option>
)

class Settings extends React.Component {
    constructor(props) {
        super();
        this.state = { 
                baseMinutes: 0, 
                baseSeconds: 0, 
                varMinutes: 0, 
                varSeconds: 0 
            };

        this.updateBaseMin = this.updateBaseMin.bind(this);
        this.updateBaseSec = this.updateBaseSec.bind(this);
        this.updateVarMin = this.updateVarMin.bind(this);
        this.updateVarSec = this.updateVarSec.bind(this);
        this.renderTimer = this.renderTimer.bind(this);
    }


    updateBaseMin(event) {
        this.setState({ baseMinutes: event.target.value });
    }

    updateBaseSec(event) {
        this.setState({ baseSeconds: event.target.value });
    }

    updateVarMin(event) {
        this.setState({ varMinutes: event.target.value });
    }

    updateVarSec(event) {
        this.setState({ varSeconds: event.target.value });
    }

    renderTimer(e) {
        e.preventDefault();
        const { baseMinutes, baseSeconds, varMinutes, varSeconds } = this.state;
            return(
                <Timer baseMinutes={baseMinutes} baseSeconds={baseSeconds} varMinutes={varMinutes} varSeconds={varSeconds}/>
            )
    }




    render() {

        const varMin = [];
        for (var i=0; i <= this.state.baseMinutes; i++) {
            varMin.push(i);
        }
        const displayBaseMin = varMin.map((minute) => 
            <option value={minute}>{minute}</option>
        )

        const varSec = [];
        for (var i=0; i <= this.state.baseSeconds; i++) {
            varSec.push(i);
        }
        const displayBaseSec = varSec.map((second) =>
            <option value={second}>{second}</option>
        )

        const { baseMinutes, baseSeconds, varMinutes, varSeconds } = this.state;


    return (

        <Container>
            Settings
            <form onSubmit={this.renderTimer}>BaseTime
                <select onChange={this.updateBaseMin}>
                    {displayMinutes}
                </select>
                :
                <select onChange={this.updateBaseSec}>
                    {displaySeconds}
                </select>
                VarTime +-
                <select onChange={this.updateVarMin}>
                    {displayBaseMin}
                </select>
                :
                <select onChange={this.updateVarSec}>
                    {displayBaseSec}
                </select>
                <input type="submit" value="Submit" />
            </form>

            <p>{this.state.baseMinutes}, {this.state.baseSeconds}, {this.state.varMinutes}, {this.state.varSeconds}</p>

            <div>{this.renderTimer}</div>
            <Timer baseMinutes={baseMinutes} baseSeconds={this.state.baseSeconds} varMinutes={varMinutes} varSeconds={varSeconds}/>
        </Container >
    )
}
}

export default Settings

Timer 的子组件:

class Timer extends React.Component {
    constructor(props) {
        super(props);
        this.state = { 
                minutes: 0,
                seconds: 0,
                baseSeconds: this.props.baseSeconds
        }

    this.go = this.go.bind(this);
    this.stop = this.stop.bind(this);
    this.reset = this.reset.bind(this);
    }

    go = () => {

        this.timer = setInterval(() => {

            if ((this.state.seconds) === (this.props.baseSeconds)) {

                clearInterval(this.timer);

            } else {
                this.setState({ seconds: this.state.seconds + 1 })
                console.log(this.state.baseSeconds)
            }
        }, 1000)



    }

    stop = () => {
       clearInterval(this.timer);
    }

    reset = () => {
        this.setState({ minutes: 0, seconds: 0 })
    }


    render() {


        return (
            <div>
                <button onClick={this.go}>start</button>
                <button onClick={this.stop}>stop</button>
                <button onClick={this.reset}>reset</button>
                <p>{this.props.baseMinutes}:{this.props.baseSeconds}</p>

                <p>{this.state.minutes}:{this.state.seconds}</p>
            </div>

        )
    }
}

export default Timer

是的,默认情况下,道具的更改会导致重新渲染。 但是在您的情况下,在子组件中,初始状态( baseSeconds )基于不推荐的道具( this.props.baseSeconds )。 构造函数只运行一次(当组件安装时),并且在此之后的 baseSeconds 道具上的任何更新都不会被检测到。 您可以直接在渲染中使用道具,而无需使用本地状态。 如果您必须使用 props 更新本地状态,推荐的方法是使用 getDerivedStateFromProps 生命周期方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM