0

我想用 ref 实现在此组件外部单击按钮时打开 react-datepicker 日历。如果它在条件渲染之外,它工作正常。如果我输入条件语句,我会得到 TypeError:this.calendarRef.current 为 null。它是类组件,并且 calendarRef 在构造函数中定义。

import React from 'react';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import DatePicker from "react-datepicker";

const MyCustomDatePicker = React.forwardRef((props, ref) => (
   <DatePicker
    ref={ref}
    selected={new Date()}
    popperPlacement="bottom-start"
    monthsShown={2}
   />
));

class DateRangeCustom extends React.Component {
    constructor(props) {
       super(props);
       this.state = {
          currentDate: '01/12/2021',
          ddCalendarOn: false,
          endDate: '08/12/2021',
    };

    this.calendarRef = React.createRef();
}

handleCalendarBtnClick = () => {
    console.log('*** HANDLE CALENDAR BTN ***');
    this.setState((state) => ({
        ddCalendarOn: !state.ddCalendarOn
    }));
    this.calendarRef.current.setOpen(true);
}

render() {
    console.log('*** render ****')
    return (
        <Grid container>
            <Grid>
                <Grid container direction="column">
                    <Button
                        onClick={this.handleCalendarBtnClick}
                    >
                        SHOW
                    </Button>
                    {this.state.ddCalendarOn && <MyCustomDatePicker
                        ref={this.calendarRef}
                    />}                        
                </Grid>
            </Grid>
        </Grid>
    );
  }
}

export default DateRangeCustom;

谢谢你的任何建议。

4

2 回答 2

0

我的错,

很简单的事情和愚蠢的错误。不需要使用 ref 或 forwardRef。只需将 open 设置为与渲染条件相同的变量即可使其工作。

import React from 'react';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import DatePicker from "react-datepicker";

class DateRangeCustom extends React.Component {
    constructor(props) {
       super(props);
       this.state = {
          currentDate: '01/12/2021',
          ddCalendarOn: false,
          endDate: '08/12/2021',
    };
}

handleCalendarBtnClick = () => {
    console.log('*** HANDLE CALENDAR BTN ***');
    this.setState((state) => ({
        ddCalendarOn: !state.ddCalendarOn
    }))
}

render() {
    console.log('*** render ****')
    return (
        <Grid container>
            <Grid>
                <Grid container direction="column">
                    <Button
                        onClick={this.handleCalendarBtnClick}
                    >
                        SHOW
                    </Button>
                    {this.state.ddCalendarOn && <DatePicker
                       open={this.state.ddCalendarOn}
                       selected={new Date()}
                       popperPlacement="bottom-start"
                       monthsShown={2}
                    />}                        
                </Grid>
            </Grid>
        </Grid>
    );
  }
}

export default DateRangeCustom;
于 2021-01-31T10:06:43.723 回答
0

ref 在渲染后注册在组件上。但是你有条件地渲染它: this.state.ddCalendarOn 然后尝试直接调用它。这将不起作用,因为状态更改将导致渲染,然后才注册 ref。

我会尝试使用更具声明性的方法,我认为 API 允许这样做。就像是:

<MyCustomDatePicker ref={this.calendarRef} open={this.state.ddCalendarOn}/>

然后您处理 Callendar 组件本身的打开状态。React 考虑尽可能使用这种声明性方法,并且很少需要使用 ref 来强制调用某些东西。当您将 Callendar 的“open”属性设置为 false 时,Callendar 将不会呈现,结果应该是相同的。

于 2021-01-31T02:10:23.683 回答