REACT ref.current 在条件渲染组件中为 null
REACT ref.current is null in conditional rendered component
我想在带有 ref 的组件外部单击按钮时实现打开 react-datepicker 日历。如果它在条件渲染之外,它工作正常。如果我输入条件语句,我会得到 TypeError: this.calendarRef.current is null。它是 class 组件并且 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;
感谢您的任何建议。
ref 在渲染后注册到组件上。但是你有条件地渲染它:this.state.ddCalendarOn
然后尝试直接调用它。这将不起作用,因为状态更改将导致渲染,然后才注册 ref。
我会尝试使用更具声明性的方法,我认为 API 允许这样做。类似于:
<MyCustomDatePicker ref={this.calendarRef} open={this.state.ddCalendarOn}/>
然后您处理 Callendar 组件本身的打开状态。 React 考虑到尽可能使用这种声明式方法,并且只有在很少情况下您才需要使用 ref 来强制调用某些东西。当您将其“open”属性设置为 false 时,Callendar 将不会呈现,结果应该是相同的。
我的错,
很简单的事情和愚蠢的错误。不需要使用 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;
我想在带有 ref 的组件外部单击按钮时实现打开 react-datepicker 日历。如果它在条件渲染之外,它工作正常。如果我输入条件语句,我会得到 TypeError: this.calendarRef.current is null。它是 class 组件并且 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;
感谢您的任何建议。
ref 在渲染后注册到组件上。但是你有条件地渲染它:this.state.ddCalendarOn 然后尝试直接调用它。这将不起作用,因为状态更改将导致渲染,然后才注册 ref。
我会尝试使用更具声明性的方法,我认为 API 允许这样做。类似于:
<MyCustomDatePicker ref={this.calendarRef} open={this.state.ddCalendarOn}/>
然后您处理 Callendar 组件本身的打开状态。 React 考虑到尽可能使用这种声明式方法,并且只有在很少情况下您才需要使用 ref 来强制调用某些东西。当您将其“open”属性设置为 false 时,Callendar 将不会呈现,结果应该是相同的。
我的错,
很简单的事情和愚蠢的错误。不需要使用 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;