react-datepickerのcustomInputにrefを適用する方法です。
まずはサンプルを。
import React from "react";
import DatePicker from "react-datepicker";
interface InputProps {
inputRef: React.Ref<HTMLInputElement>;
onClick?: React.MouseEventHandler<HTMLInputElement>;
onChange?: React.ChangeEventHandler<HTMLInputElement>;
value?: string | ReadonlyArray<string> | number;
}
const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
return <input
type="text"
ref={props.inputRef}
onClick={props.onClick}
onChange={props.onChange}
value={props.value}
/>;
})
interface Props {
inputRef: React.Ref<HTMLInputElement>;
}
const DP: React.FC<Props> = props => {
const [selected, setSelected] = React.useState<Date | null>(null);
const onChangeDatePicker = (date: Date | [Date, Date] | null) => {
if (date && date instanceof Date) {
setSelected(date);
}
};
return (
<DatePicker
selected={selected}
onChange={onChangeDatePicker}
customInput={
<Input inputRef={props.inputRef} />
} />
);
};
const App: React.FC = () => {
const ref = React.useRef<HTMLInputElement>(null);
const onClick: React.MouseEventHandler<HTMLButtonElement> = event => {
console.log(ref.current?.value);
};
return (
<form>
<DP inputRef={ref} /><br/>
<button type="submit" onClick={onClick}>送信</button>
</form>
);
};
順番に説明していきます。
customInputに指定するコンポーネント
DatePicker の customInput に指定するコンポーネントは以下のように定義します。
interface InputProps {
inputRef: React.Ref<HTMLInputElement>; // ①
onClick?: React.MouseEventHandler<HTMLInputElement>; // ②
onChange?: React.ChangeEventHandler<HTMLInputElement>; // ②
value?: string | ReadonlyArray<string> | number; // ②
}
const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => { // ③
return <input
type="text"
ref={props.inputRef} // ④
onClick={props.onClick}
onChange={props.onChange}
value={props.value}
/>;
})
① プロパティにReact.Ref型の値を定義
プロパティにReact.Ref型の値を定義します。
名称はref以外にする必要があります。
② プロパティにcustomInputとして動作するための値を定義
プロパティにonChange``onClick``valueを定義します。
これらを定義しなければDatePickerのcustomInputとして正常に動作しません。
③ コンポーネントはforwardRefで定義
refを親子間で受け渡せるようforwardRefでコンポーネントを定義します。
ただし引数refは使用しません。
④ refを適用したいコンポーネントにプロパティを指定
refを適用したいコンポーネントにforwardRefの引数ではなくプロパティのReact.Ref型の値を指定します。
DatePickerの定義
customInputに指定するコンポーネントを定義したら、これを使用してDatePickerを定義します。
interface Props {
inputRef: React.Ref<HTMLInputElement>; // ⑤
}
const DP: React.FC<Props> = props => {
const [selected, setSelected] = React.useState<Date | null>(null);
const onChangeDatePicker = (date: Date | [Date, Date] | null) => {
if (date && date instanceof Date) {
setSelected(date);
}
};
return (
<DatePicker
selected={selected}
onChange={onChangeDatePicker}
customInput={
<Input inputRef={props.inputRef} /> // ⑥
} />
);
};
⑤ プロパティにReact.Ref型の値を定義
プロパティにReact.Ref型の値を定義します。
名称はref以外にしたほうが無難です。
⑥ customInputのコンポーネントにプロパティを指定
customInputのコンポーネントにプロパティのReact.Ref型の値を指定します。
useRefの定義
const App: React.FC = () => {
const ref = React.useRef<HTMLInputElement>(null); // ⑦
const onClick: React.MouseEventHandler<HTMLButtonElement> = event => {
console.log(ref.current?.value); // ⑧
};
return (
<form>
<DP inputRef={ref} /><br/> // ⑨
<button type="submit" onClick={onClick}>送信</button>
</form>
);
};
⑦ refを定義
useRefでrefを定義します。
⑧ refの使用
イベントハンドラ等でrefを使用します。
⑨ refを適用
refを適用します。