MofuMofu2 / react-sandbox

React.js Sandbox
1 stars 0 forks source link

7-4 コンポーネントの複数階層で値を受け渡しする – useContext関数 #69

Closed MofuMofu2 closed 11 months ago

MofuMofu2 commented 1 year ago

昔やったけど全然動かなかったやつだ。テストの書き方も謎。一度GPTとCopilotさんに出してもらおう

MofuMofu2 commented 11 months ago

ReactのContextを使用したサンプルと、それに対するReact Testing Libraryを使ったテストの例を提供します。

React Contextのサンプル

まず、ReactのContextを使ってデータを共有する簡単なコンポーネントを作成します。ここでは、ユーザー名をアプリ全体で共有するシンプルな例を示します。

  1. UserContextの作成

    import React, { createContext, useState } from 'react';
    
    // UserContextの作成
    export const UserContext = createContext(null);
    
    // UserProviderコンポーネント
    export const UserProvider = ({ children }) => {
     const [username, setUsername] = useState('Guest');
    
     return (
       <UserContext.Provider value={{ username, setUsername }}>
         {children}
       </UserContext.Provider>
     );
    };
  2. UserContextの使用

    import React, { useContext } from 'react';
    import { UserContext } from './UserContext';
    
    // ユーザー名を表示するコンポーネント
    const UserDisplay = () => {
     const { username } = useContext(UserContext);
    
     return <div>Hello, {username}!</div>;
    };
    
    export default UserDisplay;
  3. Appコンポーネント

    import React from 'react';
    import { UserProvider } from './UserContext';
    import UserDisplay from './UserDisplay';
    
    const App = () => {
     return (
       <UserProvider>
         <UserDisplay />
       </UserProvider>
     );
    };
    
    export default App;

React Testing Libraryでのテスト

React Testing Libraryを使用して上記のContextをテストする方法を示します。

  1. UserDisplayコンポーネントのテスト

    import React from 'react';
    import { render, screen } from '@testing-library/react';
    import { UserProvider } from './UserContext';
    import UserDisplay from './UserDisplay';
    
    test('displays the default username', () => {
     render(
       <UserProvider>
         <UserDisplay />
       </UserProvider>
     );
    
     expect(screen.getByText(/hello, guest!/i)).toBeInTheDocument();
    });

このテストでは、UserProviderを使ってUserDisplayコンポーネントをラップし、デフォルトのユーザー名(この場合は「Guest」)が正しく表示されるかを確認しています。

ReactのContextを使うと、状態や関数などをアプリのどの部分からでもアクセスできるようになり、テストにおいてはReact Testing Libraryを使用してUIの変更が正しく反映されるかを検証できます。

MofuMofu2 commented 11 months ago

Contextを登録したコンポーネントで囲んでアクセスすればいいらしい

MofuMofu2 commented 11 months ago

https://react.dev/reference/react/useContext

MofuMofu2 commented 11 months ago

子コンポーネントからContextを更新できるのか?

はい、子コンポーネントからReactのContextを更新することは可能です。これを行うためには、Contextに更新関数を含めておく必要があります。上述した例に基づいて、子コンポーネントからユーザー名を更新する機能を追加する方法を説明します。

  1. UserContextの更新関数の提供

    最初のステップとして、UserContextにユーザー名を更新するための関数(setUsername)を含めます。これは上述したUserProviderコンポーネントに既に実装されています。

    export const UserProvider = ({ children }) => {
     const [username, setUsername] = useState('Guest');
    
     return (
       <UserContext.Provider value={{ username, setUsername }}>
         {children}
       </UserContext.Provider>
     );
    };
  2. 子コンポーネントでのContextの使用

    次に、子コンポーネントでUserContextを使用して、ユーザー名を更新する機能を追加します。

    import React, { useContext, useState } from 'react';
    import { UserContext } from './UserContext';
    
    // ユーザー名を更新するコンポーネント
    const UserNameChanger = () => {
     const { setUsername } = useContext(UserContext);
     const [newUsername, setNewUsername] = useState('');
    
     const handleChange = (e) => {
       setNewUsername(e.target.value);
     };
    
     const handleSubmit = () => {
       setUsername(newUsername);
     };
    
     return (
       <div>
         <input type="text" value={newUsername} onChange={handleChange} />
         <button onClick={handleSubmit}>Change Username</button>
       </div>
     );
    };
    
    export default UserNameChanger;
  3. Appコンポーネントの更新

    AppコンポーネントにUserNameChangerコンポーネントを追加して、ユーザー名の変更を可能にします。

    import React from 'react';
    import { UserProvider } from './UserContext';
    import UserDisplay from './UserDisplay';
    import UserNameChanger from './UserNameChanger';
    
    const App = () => {
     return (
       <UserProvider>
         <UserDisplay />
         <UserNameChanger />
       </UserProvider>
     );
    };
    
    export default App;

この構成では、UserProviderが提供するUserContextを介して、UserNameChangerコンポーネントがユーザー名を更新できるようになります。この方法で、ReactのContextシステムを使用して、子コンポーネントからアプリケーションの状態を効果的に管理することが可能です。