I'm trying to pass my existing Input to <DatePicker /> but it happens to be a stateless component. This seems to create two errors for me.
One is this
warning.js:36Warning: Stateless function components cannot be given refs (See ref "input" in Input created by t). Attempts to access this ref will fail.
The other is this, which seems related to #694
Uncaught TypeError: Cannot read property 'focus' of null
at t.n.setFocus (react-datepicker.min.js:1)
at react-datepicker.min.js:1
I'm not sure how best to proceed. Has anyone else encountered this scenario?
worked around this by converting it to a class component
The recommended approach is to wrap the SFC in a component class and pass the ref callback down to the SFC as a custom prop, but this library would have to convert from string refs to callbacks first.
If someone is struggling with that issue - the component that you are using as customInput prop has to be a class, not SFC.
Any updates on this? I think refs stuff could be resolved with hooks release
It would be helpfull thing, because I'm using sfc Input and now I should have one extra component only for datepicker
I agree, it would be nice to just be able to use a sfc for this. But after finding this issue I just created a regular old class component and it worked fine and now I can move on with my day 馃檪
Hmm actually I think I misunderstood this issue. I thought the issue was that the component used for the customComponent prop had to be a class component, which is no big deal. But I am using this datepicker within a larger stateless functional component, and that seems to be the real source of the problem, or at least the bigger problem. And that does suck. I don't want to refactor this entire thing I'm working on all week to make the datepicker happy.
FWIW my custom input component looks like this:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import styles from './customDateInput.css';
class CustomDateInput extends Component {
render() {
const {
onClick,
disabled,
value,
} = this.props;
return (
<>
<button
className={classNames(
styles.input,
{ [styles.isDisabled]: disabled },
)}
type="button"
onClick={onClick}
>
{value}
</button>
</>
);
}
}
CustomDateInput.defaultProps = {
value: '',
};
CustomDateInput.propTypes = {
onClick: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired,
value: PropTypes.string,
};
export default CustomDateInput;
it's being used like this in my sfc:
import CustomDateInput from './customDateInput';
...
const MyComponent = (props) => {
...
return (
<DatePicker
customInput={<CustomDateInput />}
selected={playlistDate}
onChange={handleDateChange}
maxDate={now}
disabled={showSearch}
className={styles.singleDatePicker}
/>
);
and I'm still getting this error:
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Check the render method of `DatePicker`.
in StyleLogger(CustomDateInput) (created by DatePicker)
in div (created by DatePicker)
in div (created by InnerReference)
in InnerReference (created by Context.Consumer)
in Reference (created by PopperComponent)
in Manager (created by PopperComponent)
in PopperComponent (created by DatePicker)
You can still use a SFC as your CustomDateInput if you want.
The solution is to use React's forwardRef.
You can update your ./customDateInput.js file to look like this..
import React, { forwardRef } from 'react';
const CustomDateInput = (props, ref) => {
// blah blah
};
export default forwardRef(CustomDateInput);
Note that customDateInput cannot have propTypes or defaultProps declarations since it isn't exactly a React component at this point. It's merely serving as a render function. (You'd get console warnings if specify propTypes or defaultProps)
This worked for me thanks @mfalade
import React, { forwardRef } from 'react';
//here instead of curly bracket I will have normal brackets i.e ()
const CustomDateInput = (props, _ref) => (
// blah blah
);
export default forwardRef(CustomDateInput);
Building on @mfalade and @hiranvikas77, a full example:
BTW: Works flawlessly if you want to use Reactstrap. Just import Input from reactstrap/lib/Input, then replace input with Input. Of course the popup styles are a bit different.
import React, { forwardRef, useState } from 'react'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
function Example() {
const [startDate, setStartDate] = useState(new Date())
const ref = React.createRef()
const CustomDateInput = forwardRef(({ onClick, value }, ref) => (
<input onClick={onClick} value={value} onChange={onClick} ref={ref} />
))
return (
<DatePicker
selected={startDate}
onChange={date => setStartDate(date)}
customInput={<CustomDateInput ref={ref} />}
/>
)
}
export default Example
A combination of @hiranvikas77 and @jmlivingston solution (with no IDE warnings), full example with Semantic-UI input component:
import React, { useState, forwardRef } from 'react';
import ReactDatePicker from 'react-datepicker';
import { Input, Icon } from 'semantic-ui-react';
import 'react-datepicker/dist/react-datepicker-cssmodules.css';
const DatePicker = () => {
const [startDate, setStartDate] = useState(null);
const ref = React.createRef();
const CustomInput = forwardRef(({ value, onClick }, _ref) => (
<Input
label={{ basic: true, content: <Icon name="calendar alternate outline" size="large" /> }}
labelPosition="right"
value={value}
onClick={onClick}
ref={_ref}
/>
));
return (
<ReactDatePicker
selected={startDate}
onChange={date => setStartDate(date)}
customInput={<CustomInput ref={ref} />}
/>
);
};
export default DatePicker;
I'm used in below scenario, but it's showing the below error, please help me to fix the issue.
index.js:1375 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Check the render method of r.
in CustomDatePicker (at TraceScreen.js:243)
in div (created by r)
in div (created by InnerReference)
in InnerReference (created by Context.Consumer)
in Reference (created by r)
in Manager (created by r)
in r (created by r)
in r (at TraceScreen.js:243).....
const CustomDatePicker = ({ value, onClick, labelVal, inputname }) => (
@jmlivingston Thanks a lot, it works great, but I have a problem, when I use form.reset() in parent functional component Form, it doesn't clean up, do you know how I can solve it?
This should be written in the documentation. Copy paste from the documentation fails.
() => {
const [startDate, setStartDate] = useState(new Date());
const ExampleCustomInput = ({ value, onClick }) => (
<button className="example-custom-input" onClick={onClick}>
{value}
</button>
);
return (
<DatePicker
selected={startDate}
onChange={date => setStartDate(date)}
customInput={<ExampleCustomInput />}
/>
);
};
This results in:
Check the render method of `r`.
in ExampleCustomInput (created by r)
in div (created by r)
in div (created by InnerReference)
in InnerReference (created by Context.Consumer)
in Reference (created by r)
in Manager (created by r)
in r (created by r)
Building on @mfalade and @hiranvikas77, a full example:
BTW: Works flawlessly if you want to use Reactstrap. Just
import Input from reactstrap/lib/Input, then replaceinputwithInput. Of course the popup styles are a bit different.import React, { forwardRef, useState } from 'react' import DatePicker from 'react-datepicker' import 'react-datepicker/dist/react-datepicker.css' function Example() { const [startDate, setStartDate] = useState(new Date()) const ref = React.createRef() const CustomDateInput = forwardRef(({ onClick, value }, ref) => ( <input onClick={onClick} value={value} onChange={onClick} ref={ref} /> )) return ( <DatePicker selected={startDate} onChange={date => setStartDate(date)} customInput={<CustomDateInput ref={ref} />} /> ) } export default Example
Thanks, it worked for me
@jmlivingston Thank you!
I Had an issue passing ref deeper to a functional component, the way it worked:
import React, { forwardRef, useState } from 'react'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
function Example() {
const [startDate, setStartDate] = useState(new Date())
const ref = React.createRef()
const MyCustomInput = ({ref, ...restProps})=> {
return <input ref={ref} />
}
const CustomDateInput = forwardRef(({ onClick, value }, ref) => (
<MyCustomInput onClick={onClick} value={value} onChange={onClick} parentRef={ref} />
));
return (
<DatePicker
selected={startDate}
onChange={date => setStartDate(date)}
customInput={<CustomDateInput ref={ref} />}
/>
)
}
export default Example
Most helpful comment
Building on @mfalade and @hiranvikas77, a full example:
BTW: Works flawlessly if you want to use Reactstrap. Just
import Input from reactstrap/lib/Input, then replaceinputwithInput. Of course the popup styles are a bit different.