🎃

[React]PHPerがReactを始めてみたら早速つまづいた件

2024/10/24に公開
2

前回の記事
https://zenn.dev/kkyoka/articles/ebc370c9b2a4c3

初心者らしくつまづいたのでそれを記録していきます。

型の話

async function fetchUsers(): Array {
    // ゴニョゴニョ
}

と書いていたら非同期関数または非同期メソッドの戻り値の型は、グローバル Promise<T> 型である必要があります。と怒られました。

Promiseとは、ES2015で導入された、非同期処理の状態や結果を表現するオブジェクトのことです。

とのこと。
TにはPromiseが解決したときの型が入るらしい。

ではこちらで( 。・ω・)っ

async function fetchUsers(): Promise<Array> {
   // ゴニョゴニョ
}

次はジェネリック型 'Array<T>' には 1 個の型引数が必要です。と怒られました。
配列の要素の型も定義が必要らしい。

async function fetchUsers(): Promise<User[]> {
    // ゴニョゴニョ
}

こちらでようやく解決。(Userは別途定義されている型)

非同期処理の話

// APIコールメソッド
async function fetchUsers(): Promise<User[]> {
    const response = await fetch('https://hogehoge.com');
    return await response.json();
}

// レンダーメソッド
function ComposentExample() {
    const [users, setUsers] = useState<User[]>([]);
    useEffect(() => {
        setUsers(fetchUsers());
    }, []);

    return (
        <>
            <div>ほげ〜</div>
        </>
    );
}

と書いていたら型 'Promise<User[]>' の引数を型 'SetStateAction<User[]>' のパラメーターに割り当てることはできません。と怒られました。
fetchUsers()は非同期なので、そのまま呼び出すとPromiseを返すそう。
そのため実際の値を取得するまで待つ必要があります。
そこで以下のようにfetchUsers()を呼び出す箇所にawaitを記載すれば解消されました。
そしてawaitを使うにはメソッドを非同期にする必要があるので、asyncを追記。

// APIコールメソッド
async function fetchUsers(): Promise<User[]> {
    const response = await fetch('https://hogehoge.com');
    return response.json();
}

// レンダーメソッド
function ComposentExample() {
    const [users, setUsers] = useState<User[]>([]);
    useEffect(() => {
        async function callGetUsersAPI() {
            setUsers(await fetchUsers()); // fetchUsers()の前にawaitを追記
        }
        callGetUsersAPI();
    }, []);

    return (
        <>
            <div>ほげ〜</div>
        </>
    );
}

こちらで解決。

関数の話

コンポーネント定義して、propsの型も定義するお( 。・ω・)っ

interface Name {
    last_name: string;
    first_name: string;
}

// propsはName型
function MyNameComponent(myName: Name) {
    return (
        <>
            MyName:
            <span>{myName.last_name}</span>
            <span>{myName.first_name}</span>
        </>
    );
}

export default function App() {
    const name: Name= {
        last_name: "山田", 
        first_name: "花子"
    }
    return (
        <>
            <MyNameComponent myName={name}/> // nameをドゾ〜( 。・ω・)っ
        </>
      );
};

そうすると<MyNameComponent myName=name/>のところで型 '{ myName: Name; }' を型 'IntrinsicAttributes & Name' に割り当てることはできません。と怒られました。
えっ、なーに言ってんだオメー( ◠‿◠ )。

どうやらJavaScriptで関数の引数にオブジェクトの変数を直接渡すには別の書き方にしないといけないらしい。

// MyNameComponentの引数の書き方を変更
function MyNameComponent({myName}: {myName: Name}) {
    return (
        <>
            MyName:
            <span>{myName.last_name}</span>
            <span>{myName.first_name}</span>
        </>
    );
}

こちらに変更したら解決。
デストラクチャリング構文という名前の書き方らしい。

デストラクチャリングとは、オブジェクトを変数に代入したり、必要なプロパティだけを取捨選択できる機能です。

とのこと。

const name: Name= {
    last_name: "山田", 
    first_name: "花子"
}
const { last_name } = name;
console.log(last_name ); // 「山田」で出力される

↑つまりこういうことらしい。

他にも色々書き方はあるみたい。
https://qiita.com/kimascript/items/e5514daa873b60b2ed13
既存コード参考にしながら慣れていきたい。

感想

型〜

参考

Discussion

MeguriMeguri

突然のコメント失礼します。とても参考になりました!特に非同期処理や型の話は、私も同じように苦労した経験があります。私最近APIを使ったプロジェクトに取り組んでいるのですが、今はECHOAPIというツールを使っていて、オフラインでも使えるので、開発環境が整いやすいんです。おすすめします!

きょうかきょうか

コメントありがとうございます!
ECHOAPI、初めて聞きました
機会があれば触ってみますm(__)m!