在 React 中基于子组件状态禁用按钮
Disabling button based on child component state in React
我正在使用倒计时组件作为子组件。
我想 disable/reable 一个基于计数器状态值的按钮,但我似乎无法正确读取该值。
这是我试过的。
这是倒计时组件:
import React from "react";
import PropTypes from "prop-types";
export default class Counter extends React.Component {
constructor() {
super();
this.state = { time: {}, seconds: 15 };
this.timer = 0;
this.startTimer = this.startTimer.bind(this);
this.countDown = this.countDown.bind(this);
}
secondsToTime(secs){
let hours = Math.floor(secs / (60 * 60));
let divisor_for_minutes = secs % (60 * 60);
let minutes = Math.floor(divisor_for_minutes / 60);
let divisor_for_seconds = divisor_for_minutes % 60;
let seconds = Math.ceil(divisor_for_seconds);
let obj = {
"h": hours,
"m": minutes,
"s": seconds
};
return obj;
}
componentDidMount() {
let timeLeftVar = this.secondsToTime(this.state.seconds);
this.setState({ time: timeLeftVar });
}
startTimer() {
if (this.timer === 0 && this.state.seconds > 0) {
this.timer = setInterval(this.countDown, 1000);
} else if ((this.timer === 0 && this.state.seconds === 0)){
this.state.seconds = 15;
this.timer = setInterval(this.countDown, 1000);
}
}
countDown() {
// Remove one second, set state so a re-render happens.
let seconds = this.state.seconds - 1;
this.setState({
time: this.secondsToTime(seconds),
seconds: seconds,
});
// Check if we're at zero.
if (seconds === 0) {
clearInterval(this.timer);
this.timer = 0;
console.log("counter is 0");
console.log(this.state.seconds);
console.log(this.timer);
}
}
render() {
this.startTimer();
return(
<span className={
this.state.seconds === 0 ? 'timerHidden' : 'timerActive'
}>
({this.state.time.s})
</span>
);
}
}
以及我如何读取它并在父组件中重置它:
import Counter from '../Counter/Counter.js';
export default class Verify extends React.Component {
state = {
username: this.username,
email: this.email,
code: ""
};
constructor(props) {
super(props);
this.child = React.createRef();
}
resetTimer = () => {
this.child.current.startTimer();
};
resendConfirmationCode = async e =>{
this.resetTimer();
...
}
return (
<button
className="btn btn-primary register empty"
type="button"
disabled={this.child.current.seconds > 0}
onClick={this.resendConfirmationCode}>Resend code <Counter ref={this.child}/>
</button>
);
插入计数器工作正常,也可以重置,但禁用按钮会引发以下错误:
TypeError: Cannot read property 'seconds' of null
Verify.render
> 109 | disabled={this.child.current.seconds > 0}
this.child
ref 将在初始渲染时 null/undefined。如果计数器组件由于某种原因不可用,您可能还想禁用该按钮,因此您可以只检查 ref 的当前值是假的还是真值以及 state.seconds
的 child大于 0.
<button
...
disabled={!this.child.current || this.child.current.state.seconds > 0}
onClick={this.resendConfirmationCode}
>
Resend code
</button>
<Counter ref={this.child} />
如果我们反转第二个条件,我们可以使用可选链接将它们组合成一个比较。
<button
...
disabled={!this.child.current?.state.seconds <= 0}
onClick={this.resendConfirmationCode}
>
Resend code
</button>
<Counter ref={this.child} />
我正在使用倒计时组件作为子组件。 我想 disable/reable 一个基于计数器状态值的按钮,但我似乎无法正确读取该值。
这是我试过的。 这是倒计时组件:
import React from "react";
import PropTypes from "prop-types";
export default class Counter extends React.Component {
constructor() {
super();
this.state = { time: {}, seconds: 15 };
this.timer = 0;
this.startTimer = this.startTimer.bind(this);
this.countDown = this.countDown.bind(this);
}
secondsToTime(secs){
let hours = Math.floor(secs / (60 * 60));
let divisor_for_minutes = secs % (60 * 60);
let minutes = Math.floor(divisor_for_minutes / 60);
let divisor_for_seconds = divisor_for_minutes % 60;
let seconds = Math.ceil(divisor_for_seconds);
let obj = {
"h": hours,
"m": minutes,
"s": seconds
};
return obj;
}
componentDidMount() {
let timeLeftVar = this.secondsToTime(this.state.seconds);
this.setState({ time: timeLeftVar });
}
startTimer() {
if (this.timer === 0 && this.state.seconds > 0) {
this.timer = setInterval(this.countDown, 1000);
} else if ((this.timer === 0 && this.state.seconds === 0)){
this.state.seconds = 15;
this.timer = setInterval(this.countDown, 1000);
}
}
countDown() {
// Remove one second, set state so a re-render happens.
let seconds = this.state.seconds - 1;
this.setState({
time: this.secondsToTime(seconds),
seconds: seconds,
});
// Check if we're at zero.
if (seconds === 0) {
clearInterval(this.timer);
this.timer = 0;
console.log("counter is 0");
console.log(this.state.seconds);
console.log(this.timer);
}
}
render() {
this.startTimer();
return(
<span className={
this.state.seconds === 0 ? 'timerHidden' : 'timerActive'
}>
({this.state.time.s})
</span>
);
}
}
以及我如何读取它并在父组件中重置它:
import Counter from '../Counter/Counter.js';
export default class Verify extends React.Component {
state = {
username: this.username,
email: this.email,
code: ""
};
constructor(props) {
super(props);
this.child = React.createRef();
}
resetTimer = () => {
this.child.current.startTimer();
};
resendConfirmationCode = async e =>{
this.resetTimer();
...
}
return (
<button
className="btn btn-primary register empty"
type="button"
disabled={this.child.current.seconds > 0}
onClick={this.resendConfirmationCode}>Resend code <Counter ref={this.child}/>
</button>
);
插入计数器工作正常,也可以重置,但禁用按钮会引发以下错误:
TypeError: Cannot read property 'seconds' of null
Verify.render
> 109 | disabled={this.child.current.seconds > 0}
this.child
ref 将在初始渲染时 null/undefined。如果计数器组件由于某种原因不可用,您可能还想禁用该按钮,因此您可以只检查 ref 的当前值是假的还是真值以及 state.seconds
的 child大于 0.
<button
...
disabled={!this.child.current || this.child.current.state.seconds > 0}
onClick={this.resendConfirmationCode}
>
Resend code
</button>
<Counter ref={this.child} />
如果我们反转第二个条件,我们可以使用可选链接将它们组合成一个比较。
<button
...
disabled={!this.child.current?.state.seconds <= 0}
onClick={this.resendConfirmationCode}
>
Resend code
</button>
<Counter ref={this.child} />