Wrapping DatePicker in a styled-component prevents typing of dates
A convenient way to apply custom styling with react-datepicker is to wrap the <DatePicker /> component using the popular styled-components library. For example:
const Wrapper = styled.div`
.react-datepicker {
box-shadow: 3px 2px 11px rgb(0 0 0 / 30%);
}
.react-datepicker__input-container input {
width: ${props.width || "auto"};
}
`;
return (
<Wrapper>
<DatePicker
onChange={date => setSelectedDate(date)}
selected={selectedDate}
/>
</Wrapper>
);
The Issue
Wrapping <DatePicker /> as above causes any typed entry of text that can be interpreted as a date to immediately select that date and de-focus the field — exactly as if the date had been clicked from the calendar popup. For example, typing 3 into the field will immediately populate the date 03/01/2021, instead of allowing the user to continue typing the rest of a date interactively. Typing a non-date value like - will allow the user to continue typing until a valid date is recognized. If you type ---3, you're fine until the 3, at which point the number ---3 is interpreted as the date 03/01/2021.
Wrapping <DatePicker /> in a plain <div> does not cause this problem.
Wrapping <DatePicker /> in a <Wrapper /> does cause this problem, even if the wrapper contains no styles at all.
Minimal Repro Case
...
import DatePicker from "react-datepicker";
import styled from "styled-components";
const [selectedDate, setSelectedDate] = useState(null);
const Wrapper = styled.div`
`;
return (
<Wrapper>
<DatePicker
onChange={date => setSelectedDate(date)}
selected={selectedDate}
/>
</Wrapper>
);
The expected behavior here would be that the user is allowed to begin typing text like 4/1/2024, and the cursor would remain in the field and allow that date to continue to be typed.
The observed behavior is that the instant the 4 is typed, the field is populated and defocused. Swapping out <Wrapper> for a plain <div> allows the correct behavior again.
In all other ways, the styled wrapper approach works fine.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Bump. Still a problem.
I think this is down to how you have defined your Wrapper. Styled components should be defined outside otherwise any change to state will cause them to be recreated. The typed input is changing state which recreates your Wrapper and unmounts its children.
import DatePicker from "react-datepicker";
import styled from "styled-components";
const Wrapper = styled.div``; // Moved outside of Calendar component
const Calendar = () => {
const [selectedDate, setSelectedDate] = useState(null);
return (
<Wrapper>
<DatePicker
onChange={date => setSelectedDate(date)}
selected={selectedDate}
/>
</Wrapper>
);
};
https://styled-components.com/docs/basics#define-styled-components-outside-of-the-render-method
You can wrap directly the DatePicker component like :
const Wrapper = styled(DatePicker)`
border-radius: 4px;
border: 1px solid ${colors('grey')};
`
and use the Wrapper component instead DatePicker like
<Wrapper
selected={startDate}
onChange={(date) => setStartDate(date)}
/>
Same for me, @redler except that in my case I've defined outside the styled components for CalendarContainer (and not the Wrapper) and, unfortunately, solution provided by @alimtunc doesn't work for me because no style rule is applied.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
If all you wan to do is style the calendar element, use the calendarContainer prop:
// Styled component
export const CalendarContainer = styled.div`
width: 400px;
`;
// Component
export const DatePicker = () => {
const [startDate, setStartDate] = useState(new Date());
return (
<ReactDatePicker
calendarContainer={Styled.CalendarContainer}
selected={startDate}
onChange={(date) => setStartDate(date)}
/>
);
};
This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 10 days.
This issue was closed because it has been stalled for 10 days with no activity.