ReactでnoUiSliderを使ったときの覚え書き
最近趣味で作っていたReact(実際にはNext.jsだったんですが)のサイトで、範囲を指定できるスライダーが欲しいタイミングがあったんですね。<input type="range">だとハンドルが1個しかないですし、じゃあライブラリ使うかということで探し、要件を満たしたのがnoUiSliderです。
ですが、ひとつ問題がありました。Reactに対応したnoUiSliderのライブラリが以下のくらいしか見つからなくて、しかもこれは最終更新が2021年だったんですね。
一方で、本家のほうは今年の6月に更新された形跡があります。
ということで、react-nouisliderのほうは使わずに、自分が必要な機能だけ実装したReactのコンポーネントを作成しました。以下がコードの全文です。自分が必要な機能しか実装していないので短いですね。
import { useEffect, useRef } from 'react';
import noUiSlider, { API } from 'nouislider';
import 'nouislider/dist/nouislider.css';
type Props = {
values: [number, number],
max: number,
// eslint-disable-next-line no-unused-vars
onChange: (values: [number, number]) => void,
}
function Slider(props: Props) {
const { values, max, onChange } = props;
const ref = useRef<HTMLDivElement>(null);
const slider = useRef<API|null>(null);
useEffect(() => {
slider.current = noUiSlider.create(ref.current!, {
start: values,
step: 1,
connect: true,
range: {
min: 1,
max,
},
format: {
to(value: number): number {
return Math.round(value);
},
from(value: string): number {
return Number(value);
},
},
tooltips: true,
});
slider.current.on('change', (changedValues) => {
onChange(changedValues as [number, number]);
});
return () => {
slider.current!.destroy();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
slider.current!.set(values);
}, [values]);
return (
<div ref={ref} />
);
}
export default Slider;
(改善点はめちゃくちゃ色々あると思いますが許して)
このコンポーネントは親から受け取ったvaluesをスライダーのハンドルに反映して、スライダーのハンドルが操作されたら親にイベントを渡すといった、単方向データフローを実現しています。
余談ですが、こういう入力要素に対する単方向データフローって実際どうやって作ればいいんだって疑問だったんですよね。今回自分でReact用の簡単なコンポーネントを作るにあたって、不完全ながらもやり方がわかって良かったです。
覚え書きと言いつつ本当に簡単なことしかしてないので、他に書くことも特にないですね。もしnoUiSliderをReactで使いたいという人がこの記事に辿り着いたら、ちょっとだけ参考にしてみてください。
この記事が気に入ったらサポートをしてみませんか?