- Published on
typescriptでuseRef使うときのメモ
- Authors
- Name
- Naoya 'noine' Sato
- @noineniya
ちょっとしたメモです
three.js を vite + typescript で使いたくて、最初につまづいたところ。
useRef の型
import { OrbitControls, PerspectiveCamera } from "@react-three/drei"
import { useFrame } from "@react-three/fiber"
import { ReactNode, useEffect, useRef } from "react"
type P = {
children: ReactNode
}
export const Camera:React.FC<P> = ({children}) => {
const orbitControlsRef = useRef<"ここに何いれていいか分からなかった!">(null)
useFrame((state) => {
if(orbitControlsRef.current){
const {x, y} = state.mouse
orbitControlsRef.current.setAzimuthalAngle(-x * angleToRadians(45))
orbitControlsRef.current.setPolarAngle((y + 1) * angleToRadians(90 - 30))
orbitControlsRef.current.update()
}
})
return(
<>
<PerspectiveCamera makeDefault position={[0, 0, 10]} />
<OrbitControls ref={orbitControlsRef} makeDefault />
{children}
</>
)
}
useRef<>(null)
の型を入れないと怒られちゃったけど、OrbitControls は何を指定したらいいか分からず、useRef<OrbitControls>(null)
こんな感じで使ってました。
エラー出てても描画できてたし。。
でも気持ち悪いんで調べてたら、こんな書き方がありました。どこだったか忘れちゃった…
import { OrbitControls as OrbitControlsImpl } from "three-stdlib"
const orbitControlsRef = useRef<OrbitControlsImpl>(null)
確かにエラーでなくなったんだけど、 import { OrbitControls, PerspectiveCamera } from "@react-three/drei"
ここでインポートしている OrbitControls との違いがいまいち分からない。
こういうモジュールの辿り方?を知っている方がいたら教えていただきたいです。
three.js は useRef を多用する感じなので、同じ問題にぶつかりそう…
command + クリックで辿っていく感じなのかなぁ。
おまけ
typescript をちゃんと勉強してないのが良くないんですが、こんなとこでも悩んでしまった。
Web Audio API を使って、constructor で音声入力の function をいくつか作りました。
class Mic {
loaded: boolean;
context: any;
input: any;
analyser: any;
processor: any;
spectrum: any;
res: any;
constructor() {
this.loaded = false;
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then((stream) => {
this.context = new AudioContext();
this.input = this.context.createMediaStreamSource(stream)
this.analyser = this.context.createAnalyser()
this.input.connect(this.analyser)
this.analyser.fftSize = 2048;
this.loaded = true;
})
}
//これでオーディオ処理のストップと再開
pause() {
this.context.state === "running"
?
this.context.suspend()
:
this.context.resume()
}
getLevel() {
if (this.loaded) {
//resultには周波数ごとの要素が1024格納される
const result = new Uint8Array(this.analyser.frequencyBinCount)
this.analyser.getByteFrequencyData(result)
return result.reduce((a, b) => Math.max(a, b))
}
return 0
}
getFrequencyMulti(){
if (this.loaded) {
const result = new Uint8Array(this.analyser.frequencyBinCount)
this.analyser.getByteFrequencyData(result)
const encord = Array.from(result)
return encord
}
return []
//最初return 0にしてたら戻り値の型がnumber[] | 0になってしまったので空の配列にした(自戒)
}
close() {
this.context.close()
}
}
export default Mic
getFrequencyMulti()のコメントにあるように、返り値を配列と number にしてしまっていた。
なので、返り値を受け取る所で型のエラーが出てしまっていた。mic.getFrequencyMulti().length
とかやっても「配列じゃなくて 0 の場合もあるのに length なんて使えないよ!」って怒られた(実行してくれてたけど)
ここらへんもちゃんと勉強しなきゃだけど、いつも使いながらなんですわん。
それではまた!