第4章-レンダリングan array


Array Rendering


今回は、反応で配列をレンダリングする方法を見てみましょう.オブジェクトとして存在する次の配列を持つユーザー変数を作成します.
const users = [
  {
    id: 1,
    username: '홍길동',
    email: '홍길동@gmail.com'
  },
  {
    id: 2,
    username: '이순신',
    email: '이순신@example.com'
  },
  {
    id: 3,
    username: '강감찬',
    email: '강감찬@example.com'
  }
];
これらのコンテンツを構成部品としてレンダリングする必要がある場合は、どうすればいいですか?🤔

Method 1. Rendering one by one


まず、最も簡単で、最も基本的な方法はコードを直接書くことです.
import React from 'react';

function UserList() {
  const users = [
    {
      id: 1,
      username: '홍길동',
      email: '홍길동@gmail.com',
    },
    {
      id: 2,
      username: '이순신',
      email: '이순신@example.com',
    },
    {
      id: 3,
      username: '강감찬',
      email: '강감찬@example.com',
    },
  ];

  return (
    <div>
      <div>
        <b>{users[0].username}</b> <span>{users[0].email}</span>
      </div>
      <div>
        <b>{users[1].username}</b> <span>{users[1].email}</span>
      </div>
      <div>
        <b>{users[2].username}</b> <span>{users[2].email}</span>
      </div>
    </div>
  );
}

export default UserList;
最初の数は行が分からないが、配列要素の数が増えるとコード量も長くなり、効率も低下する.

Method 2. Using the function map


最も一般的で一般的な方法はjavascript配列内蔵関数でmapを使用することです.mapは配列内の各要素を変換するために使用され、このプロセスで新しい配列が作成され、返されます.
  return (
    <div>
      {users.map((user) => (
        <User user={user} />
      ))}
    </div>
  );
  • の残りの部分は同じで、ユーザーリストが返す部分はユーザーです.map関数を利用するように変更しました.users.mapの場合、userは個別要素を加え、<User user={user} />を返します.
  • ですが、これで終わると身長警告が出てきます.Keypropsは、各要素の固有値を拡大してレンダリングのパフォーマンスを最適化します.
  •   return (
        <div>
          {users.map((user) => (
            <User user={user} key={user.id} />
          ))}
        </div>
      );
    keyを渡す場合は、固有の値、すなわち重複できない値を入力する必要があります.ここではuser.idは繰り返さないようなので、user.idが置かれています.本当に加算できる値がない場合は、推奨しませんが、インデックスを追加する方法もあります.

    What is a key?


    例えば、[a,b,c,d]があり、cの前にzが加算されると仮定する.これにより,cがzになり,dがcになると,dは新しいものになる.同様に、仮にaを削除するときもaを削除し、その位置がbになり、bがcになるとしたら...これは非常に非効率です.

    しかし、キーを指定すると、物語が異なります.キーがあれば、どの値をレンダリングするかがわかります.cの前にzを追加すると再仮定すると、bとcの間にzを追加するだけでよい.

    useRef Hook

    useRefについては、アレイへのアイテムの追加/削除/修正を行う前に理解する必要があります.useRefには2つの大きな用途があります.

    1.userefを使用して特定DOMを選択


    コンセプト


    JavaScriptを使用する場合、特定のDOMを選択する必要がある場合、getElementById()querySelector()などのDOMセレクタ関数を使用してDOMを選択します.
    反応を用いた項目では,直接DOMを選択する必要がある場合もある.例えば、以下の場合、DOMを直接選択せざるを得ない.
  • 特定の領域のサイズを取得する必要がある場合、
  • が必要である.
  • スクロールバーの位置を入力または設定する必要がある場合は、
  • を入力または設定します.
  • 焦点を設定する必要がある場合は、
  • 焦点を設定します.
  • Video.HTML 5ビデオ関連ライブラリ、例えばjs、JWPlayerまたはD 3、グラフ.外部ライブラリ(jsなど)を使用する必要がある場合は、
  • が必要です.
    このとき、反応器にはrefが用いられる.また、関数型素子でrefを使用する場合は、userefというhook関数を使用する必要があります.

    実習


    前回作成したInputFormでは、初期化ボタンをクリックして初期化ボタンにフォーカスを保持し、userefを使用して初期化ボタンをクリックすると名前入力でフォーカスが得られます.
    import React, { useState } from "react";
    
    function InputForm() {
      const [inputs, setInputs] = useState({
        name: "",
        email: "",
      });
      const nameInput = useRef();const { name, email } = inputs;
    
      const onChange = (e) => {
        const { name, value } = e.target;
    
        setInputs({
          ...inputs,
          [name]: value,
        });
      };
      const onReset = () => {
        setInputs({
          name: "",
          email: "",
        });
        nameInput.current.focus();};
    
      return (
        <div>
          <input name="name" placeholder="이름" onChange={onChange} value={name} />
          <input
            name="email"
            placeholder="이메일"
            onChange={onChange}
            value={email}
            ref={nameInput}/>
          <button onClick={onReset}>초기화</button>
          <hr />
          <div>
            <b>: </b>
            {name} ({email})
          </div>
        </div>
      );
    }
    
    export default InputForm;
  • 2useRef()を使用してRefオブジェクトを作成し、選択したいDOMのref値に設定する必要があります.
  • では、Refオブジェクトの.currentの値は、我々が望むDOMを指す.
  • したがって、
  • は、nameInput.currentがemail inputを指し、そこでfocus() DOM APIを呼び出して焦点とする.
  • 2.userefを使用して構成部品に変数を作成する


    コンセプト


    useref hookはDOMの選択に加えて、コンポーネントで表示および変更できる変数を管理する他の用途があります.
    userefは一般的なJavaScriptオブジェクトです.すなわち、heap領域に格納されているため、アプリケーションを参照するたびに同じメモリアドレスを有し、値が変更されても再表示されません.
    ただし、関数構成部品内で直接変数を宣言すると、レンダリングのたびに初期化値の問題が発生します.または、ステータス管理Hook(useState()など)を使用すると、ステータス値を変更するたびに不要なレンダリングが発生します.
    userefで作成した変数を使用して、次の値を管理できます.
  • settimeout、setIntervalによって作成されたid
  • 外部ライブラリを使用して作成するインスタンス
  • 転動位置
  • 実習


    userefを使用して、将来配列に新しいプロジェクトを追加するときに新しいプロジェクトで使用される一意のidを管理します.
    // App.js
    import React, { useRef } from "react";
    import UserList from "./UserList";
    
    function App() {
      const users = [
        {
          id: 1,
          username: "홍길동",
          email: "홍길동@gmail.com",
        },
        {
          id: 2,
          username: "이순신",
          email: "이순신@example.com",
        },
        {
          id: 3,
          username: "강감찬",
          email: "강감찬@example.com",
        },
      ];
    
      const nextId = useRef(4);// 배열에 항목을 추가하는 함수
      const onCreate = () => {
        // (... 아직 구현 안함 ...)
        nextId.current += 1;};
    
      return <UserList users={users} />;
    }
    
    export default App;
    
    useRef()を使用するときにパラメータが追加された場合、この値は.currentのデフォルト値です.また、この値を変更する場合は.current値を変更するだけで、クエリーする場合は.currentをクエリーするだけです.このようにuserefを用いる利点は、レンダリングしても状態を保つことができ、状態値を変更してもレンダリングを必要としないことである.
    // UserList.js
    import React from "react";
    
    function User({ user }) {
      return (
        <div>
          <b>{user.username}</b> <span>({user.email})</span>
        </div>
      );
    }
    
    function UserList({ users }) {
      return (
        <div>
          {users.map((user) => (
            <User user={user} key={user.id} />
          ))}
        </div>
      );
    }
    
    export default UserList;
    

    Practice 1. Add Array Item


    配列にエントリを追加するには、ユーザー名と電子メールを入力するinputとbuttonの2つが必要です.これをCreateUserと呼んでいますそれをjsという成分に分けて作ります.

    CreateUser.js

    import React from 'react';
    
    function CreateUser({ username, email, onChange, onCreate }) {
      return (
        <div>
          <input
            name="username"
            placeholder="계정명"
            onChange={onChange}
            value={username}
          />
          <input
            name="email"
            placeholder="이메일"
            onChange={onChange}
            value={email}
          />
          <button onClick={onCreate}>등록</button>
        </div>
      );
    }
    
    export default CreateUser;
    ステータス管理はCreateUserではなく、親コンポーネントAppで行い、inputの値とイベント登録の関数としてpropsに移行して使用します.

    App.js

    import React, { useRef, useState } from "react";
    import UserList from "./UserList";
    import CreateUser from "./CreateUser";
    
    function App() {
      const [inputs, setInputs] = useState({ // input 상태관리
        username: "",
        email: "",
      });
      const { username, email } = inputs;
    
      const [users, setUsers] = useState([ // 배열 상태관리
        {
          id: 1,
          username: "홍길동",
          email: "홍길동@gmail.com",
        },
        {
          id: 2,
          username: "이순신",
          email: "이순신@example.com",
        },
        {
          id: 3,
          username: "강감찬",
          email: "강감찬@example.com",
        },
      ]);
    
      const nextId = useRef(4);
      
      // input 상태 변화
      const onChange = (e) => {
        const { name, value } = e.target;
        setInputs({
          ...inputs,
          [name]: value,
        });
      };
    
      // 배열에 항목 추가하는 함수
      const onCreate = () => {
        // 배열에 항목은 어떻게 추가할까? 🤔
        // 한번 생각해서 작성해보길 바란다.
        
        setInputs({
          username: "",
          email: "",
        });
        nextId.current += 1;
      };
      
      return (
        <>
          <CreateUser
            username={username}
            email={email}
            onChange={onChange}
            onCreate={onCreate}
          />
          <UserList users={users} />
        </>
      );
    }
    
    export default App;
    
    配列にアイテムを追加する時間です.
    配列内のローは、オブジェクトと同じように不変性を保つ必要があります.したがって,配列のpush,splice,sortなどの関数は使用できない.不変性を維持しながら配列に新しい項目を追加する方法は2つあります.

    Method 1. spread

    const onCreate = () => {
      const user = {
        id: nextId.current,
        username,
        email,
      };
      
      // `[...users]`는 `[user[0], user[1], user[2], ...]`와 동일한 의미
      setUsers([...users, user]);
      setInputs({
        username: "",
        email: "",
      });
      nextId.current += 1;
    };

    Method 2. concat function

    const onCreate = () => {
      const user = {
        id: nextId.current,
        username,
        email,
      };
      // concat과 비슷한 함수로는 push가 있고 일반적으로 push가 더 많이 쓰이지만
      // 불변성을 유지하기 위해서 여기서는 concat을 사용했다.
      setUsers(users.concat(user));
      setInputs({
        username: "",
        email: "",
      });
      nextId.current += 1;
    };

    Practice 2. Remove Array Item


    今回は、配列から特定のユーザーを削除してみましょう.

    UserList.js

    import React from "react";
    
    function User({ user, onRemove }) {
      return (
        <div>
          <b>{user.username}</b> <span>({user.email})</span>
          <button onClick={() => onRemove(user.id)}>삭제</button>
        </div>
      );
    }
    
    function UserList({ users, onRemove }) {
      return (
        <div>
          {users.map((user) => (
            <User user={user} key={user.id} onRemove={onRemove} />
          ))}
        </div>
      );
    }
    
    export default UserList;

    App.js

    // 배열에 항목 삭제하는 함수
    const onRemove = (id) => {
      // user.id가 넘겨받은 id와 일치하지 않는 원소만 추출해서 새로운 배열을 만들어서 넘겨줌
      // 즉 user.id가 id인 것은 제거됨
      setUsers(users.filter((user) => user.id !== id));
    };
    削除の方法も簡単です.App.jsでonRemove関数を作成してUserListに渡し、削除ボタンをクリックすると、onRemoveに該当するuser.idを入れて呼び出せばよい.

    Practice 3. Modify Array Item


    最後に、ユーザーコンポーネントで勘定科目名をクリックすると、色を緑に変更し、もう一度クリックして黒に変更します.
    このため、appコンポーネントのusers配列のオブジェクトにactiveプロパティを最初に追加します.Activeがtrueの場合は緑、falseの場合は黒です.次に、アクティブな値に基づいて3つのトラップ演算子を使用して色値を変更するstyleを示します.
    <b style={{
        cursor: "pointer",
        color: user.active ? "green" : "black",
    }}
       onClick={() => onToggle(user.id)}
    >
    {user.username}
    </b>
    今はアプリですjsにonToggleという関数を作成し、userをクリックすると反転アクティビティ値が実現します.
    // 배열 active 수정하는 함수
    const onToggle = (id) => {
      setUsers(
        users.map((user) =>
          user.id === id ? { ...user, active: !user.active } : user
        )
      );
    };
    変更時にmap関数を使用して配列を更新し、配列の不変性を維持できます.
    パスまとめて、アレイを作成するときは拡散演算やconcat、アレイを削除するときはfilter、アレイを修正するときはmap