この記事を作った動機

 全然まだ私は使い方とか概念をわかってないと思うが、とにかくよく使う hooks について記録を取りたいので、記事を書くだけ。思考の整理とかって感じで書いていて、普通に間違い混ざってると思うし、他の人に参考になるかは怪しい。

react とデータの関係性

 React では、データが変更されると UI が連動して更新されたりするという仕組みになっているので、普通の変数ではなく、データのありように合わせて、状態変数と呼ばれるものを使い分ける必要がある。

環境

  • Vite
  • React
  • TypeScript
  • Tailwind CSS
  • zustand

普通の変数

概要

 普通に TypeScript や JavaScript で宣言するような let や var などと書いて宣言する変数たちのことである。これら変数の内容は基本的に React が再描画をかけると内容が初期化されて元の再描画前のデータは消えてしまう。

 これを防ぎ、UI 再描画をまたいで変数の値を保持するためには、状態変数を useState なり、 useRef なり宣言して利用する必要があると思われる。

export default function Acompornent(){
    // 再描画時には、x:100 y:100 にいちいち初期化されて変更内容が失われる
    let windowPos = {
        x: 100,
        y: 100
    } 

    // こちらは再描画時には内容は失われない
    const [style,setStyle] = useState({
        top:0,
        left:0
    })

    // このようなコードを書くと windowPos は setStyle されたあと再描画で内容が初期値に戻ってしまう
    addEventListener("mousemove",(event:MouseEvent) => {
        // 何かしらのコード

        windowPos.x = event.screenX
        windowPos.y = event.screenY

        // 何かしらのコード

        setStyle({
            top: windowPos.x,
            left: windowPos.y
        })
    })

    return <div style={style} className="fixed">This is styled text.</div>
}

useState

概要

 オーソドックスな状態変数で、データが更新されたとき、UI を再描画させたいという場合に使う。

import

import { useState } from "react"

宣言

// useState の中身はいろんなデータ型が入る。特定の boolean 型しか使えないとかそういうことはないようである。
const [visible,setVisible] = useState(true) 
// 厳密に型を指定することもできるようである。
const [visible,setVisible] = useState<boolean>(true) 
// 初期値が null の例
const [visible,setVisible] = useState<boolean | null>(null) 

const [data,setData] = useState({
    someItem: "itemname",
    nest:{
        "howComplexItIs":"butShowExampleForNow",
        "nestitem":["nestdata","nestdata1"]
    }
})

データを読み取る

console.log(visible)

console.log(data)
console.log(data.someItem)
console.log(data.nest.howComplexItIs)

データを更新する

 useState – React にも書いてあるが、...[変数名] みたいにすることで、とにかく前の値を引き継げるようである。

setVisible(true)
setVisible(false)

// すべてを更新する
setData({
    someItem: "aaa",
    nest:{
        "howComplexItIs":"aa",
        "nestitem":["sss,sss"]
    }
})
// 部分的に更新し、その他は元の値を保持する
setData({
    ...data,
    nest:{
        ...data.nest,
        "nestitem":[...data.nest.nestitem,"newItem"]
    }
})
// 部分的に更新し、その他は元の値を保持する
setData((state) => ({
    ...state,
    nest:{
        ...state.nest,
        "nestitem":[...state.nest.nestitem,"newItem"]
    }
}))

useRef

概要

 私は現状(2025/9/9)だと useState から、状態変数の値が変更されたときの UI 再描画を取り除いたものというイメージをもっている。通常の変数では再描画が起こると内容が失われて初期値にリセットされてしまうが、変数更新時に UI を再描画したいわけでもない場合に、データを保持するために使うっぽい?

 まとめると、再描画をまたいでデータを保持するが、データ更新時にUIを更新させたくないときに使うっぽい。

import

import { useRef } from "react"

宣言

// useState と同様に自由にいろんな型のデータを設定できる
let windowPos = useRef({
    x:100,
    y:100
})

let onMove = useRef<boolean>(false)
let onMove = useRef(false)

データを読み取る

console.log(windowPos.current.x)

console.log(onMove.current)

データを更新する

windowPos.current.y = 2342

onMove.current = false
onMove.current = true

useEffect

概要

 直接状態変数として使うものではないが、状態変数が変更されたときに、それを検出してなにか作業させたいときに使う。

import

import { useEffect } from "react"

使い方

import { useEffect, useState } from "react"
import { create } from "zustand";

// useEffect の前座 -------------------------------
// useEffect の前座 -------------------------------
type DatabaseState = {
  websocket: WebSocket | null;
  serverIP: string | null;
  changeServer: (ip: string) => void;
  closeConnection: () => void;
  getWebsocket: () => WebSocket | null;
};

export const useDatabaseStore = create<DatabaseState>((set, get) => ({
  websocket: null,
  serverIP: "ws://localhost:50097",

  changeServer: (ip: string) => {
    set({ serverIP: ip });
  },

  closeConnection: () => {
    const ws = get().websocket;
    ws?.close();
    set({ websocket: null });
  },

  getWebsocket: () => get().websocket,
}));
// useEffect の前座 -------------------------------
// useEffect の前座 -------------------------------

// ここからが useEffect の例 ----------------------------
// ここからが useEffect の例 ----------------------------
export function useDatabaseEffects() {
  const serverIP = useDatabaseStore((s) => s.serverIP);
  const setWebsocket = useDatabaseStore.setState;

  // serverIP setWebsocket などの変数のデータの変更(状態)を監視する useEffect
  useEffect(() => {
    if (!serverIP) return;

    const ws = new WebSocket(serverIP);
    setWebsocket({ websocket: ws });

    // このコードでは、一時的切っているが、return として関数を書いておくと、再描画時かuseEffectの次回実行時に、クリーンアップなど、やらせたい処理が書けるらしい? まだここはよくわかっていない。
    // return () => {
    //   ws.close();
    // };
  }, [serverIP, setWebsocket]); // 監視する状態変数のリスト
}
// ここまでが useEffect の例 ----------------------------
// ここまでが useEffect の例 ----------------------------

躓いたこと

 なんか、躓いたことについて記録を取っていたつもりが、なんか how to に近くなってしまっている気がするので、具体的に状態変数について躓いたことも記録してみようと思った次第である。

このページは、まだ未完成です。。。

nicotalk&キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html (2024年5月16日)

参考にしたサイトとか