20201020のReactに関する記事は20件です。

Qiita開発チームがReactの開発で default export を使わなくなった理由

はじめに

こんにちは、Qiita開発チームの@ohakutsuです。

現在、QiitaのフロントエンドはReact + Atomic Designで実装されています。
Atomic Designの特徴として、再利用可能な単位で分割されたコンポーネントをつくる必要があります。
しかし、分割されたコンポーネントの数は日々大きくなっていってしまい、コンポーネントの管理が難しくなってしまいます。
そこで、Qiita開発チームでは、default exportを使い実装をしていたのをやめ、named exportを使い実装を行うようになりました。
今回は、Qiita開発チームがなぜdefault exportを使わなくなったのかについてお話します。

なぜ default export を使わなくなったのか

Qiita開発チームがdefault exportを使わなくなった理由は、default exportだとimportする側で自由に名前を決められてしまうためです。

default exportを使った場合

.jsx
export default () => {
  ...
}
index.jsx
import Button from './Button'
// ↑↓自由に名前をつけることができてしまう
import SubmitButton from './SubmitButton'

...

このように、default exportにしてしまうと、import側で自由に名前をつけることができてしまい、コンポーネント名が統一されなくなってしまいます。

また、例に出したSubmitButtonを抽象化し、Buttonにした場合、ファイルパスはVSCodeなどで自動的に修正をしてくれますが、SubmitButtonButtonにはなりません。ここで、実際の実装と定義名が異なってしまいます。また、それだけではなく、異なっていたとしても動いてしまうため、発見が難しくなるといったこともあります。

named exportを使った場合

SubmitButton.jsx
export const SubmitButton = () => {
  ...
}
index.jsx
import { SubmitButton } from './SubmitButton'

...

named exportの場合、importする側ではexport側で定義された名前をそのまま使うことになります。
また、以下のようにコンポーネント名を変更した場合、

Button.jsx
export const Button = () => {
  ...
}

Submitbuttonをインポートしている側でエラーが起きます。

index.jsx
import { SubmitButton } from './Button' // ←エラーになる

...

エラーが起きるため、インポート側でのコンポーネント名の変更忘れに気づくことができます。

冒頭でもお話しましたが、Atomic Designでは、部品ごとにパーツを作り、さらに組み立てたコンポーネントをつくっていくため、どうしてもコンポーネントの数が多くなってしまいます。そこでdefault exportを使うと、コードを書く人によってコンポーネント名が変わる可能性があり、コンポーネントの管理が難しくなるといった問題が考えられます。
そのため、named exportでインポートするコンポーネント名に制限をし、コンポーネントの管理をしやすくしたというのも1つの理由です。

named exportにしたときの問題点

React.lazyはdefault exportでないと使えない

Code-Splitting – React によると、React.lazyはnamed exportには対応しておらず、

ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";
MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));

のように、named export -> default exportにするための中間コンポーネントが必要になります。
React.lazyを使う必要のあるコンポーネントの場合は、例外としてディレクトリを分けるなどして、default exportで実装するのもアリだと思います。

さいごに

Qiita開発チームでAtomic Designを行う際に、default exportを使わなくなった理由について書いてきました。
僕はまだQiita開発チームに来て4ヶ月程度しかたっておらず、まだまだ力不足ですが、これからもQiitaをよりよいものにしていくために、開発・改善を行っていきます。

また、Qiitaの質問にdefault export / named exportについての意見交換を投稿しているので、ぜひ、ご意見をお聞かせください。
[意見交換] React開発で使うならnamed export?default export? - Qiita

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳⑦ Selectors

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

  • 前書き
  • 基本チュートリアル
  • ガイド
  • APIリファレンス

全目次は一番下にあります


Selector

selectorは、divider state (派生状態)を表します。divider stateは、与えられたstateを何らかの方法で変更する純粋な関数にstateを渡す出力と考えることができます。

派生stateは、他のデータに依存する動的データを構築できるため、強力な概念です。todoリストアプリケーションのコンテキストでは、次のものが派生stateと見なされます。

  • フィルタされたtodoリスト:いくつかの基準(すでに完了している項目を除外するなど)に基づいてフィルタされた特定の項目を持つ新しいリストを作成することによって、完全なtodoリストから派生します。

  • ToDoリストの統計:リスト内の項目の総数、完了した項目の数、完了した項目の割合など、リストの有用な属性を計算することによって、完全なToDoリストから得られます。

フィルタされたtodoリストを実装するには、atomに値を保存できる一連のフィルタ条件を選択する必要があります。
使用するフィルタオプションは、「すべて表示」、「完了を表示」、および「未完了を表示」です。デフォルト値は「すべて表示」です。

const todoListFilterState = atom({
  key: 'todoListFilterState',
  default: 'Show All',
});

todoListFilterStatetodoListStateを使用して、フィルタされたリストを導出するfilteredTodoListStateselectorを構築できます。

const filteredTodoListState = selector({
  key: 'filteredTodoListState',
  get: ({get}) => {
    const filter = get(todoListFilterState);
    const list = get(todoListState);

    switch (filter) {
      case 'Show Completed':
        return list.filter((item) => item.isComplete);
      case 'Show Uncompleted':
        return list.filter((item) => !item.isComplete);
      default:
        return list;
    }
  },
});

filteredTodoListStateは内部的に2つの依存関係 (todoListFilterStatetodoListState) を追跡し、どちらかが変更された場合に再実行されるようにします。

コンポーネントの観点から見ると、selectorは、atomを読み取るために使用されるのと同じhookを使用して読み取ることができます。ただし、一部のhookは書き込み可能なstate(i.e useRecoilState())でのみ機能することに注意してください。
全てのatomは書き込み可能stateであるが、書き込み可能stateとみなされるのは一部のselectorのみである(getプロパティとsetプロパティの両方を持つselector)。このトピックの詳細は、コアコンセプトを参照してください。

フィルタリングされたtodoListの表示は、TodoListコンポーネントで1行変更するだけです。

function TodoList() {
  // changed from todoListState to filteredTodoListState
  const todoList = useRecoilValue(filteredTodoListState);

  return (
    <>
      <TodoListStats />
      <TodoListFilters />
      <TodoItemCreator />

      {todoList.map((todoItem) => (
        <TodoItem item={todoItem} key={todoItem.id} />
      ))}
    </>
  );
}

todoListFilterStateにデフォルト値「すべて表示(Show All)」が指定されているため、UIはすべてのtodoを表示していることに注意してください。
フィルタを変更するには、TodoListFiltersコンポーネントを実装する必要があります。

function TodoListFilters() {
  const [filter, setFilter] = useRecoilState(todoListFilterState);

  const updateFilter = ({target: {value}}) => {
    setFilter(value);
  };

  return (
    <>
      Filter:
      <select value={filter} onChange={updateFilter}>
        <option value="Show All">All</option>
        <option value="Show Completed">Completed</option>
        <option value="Show Uncompleted">Uncompleted</option>
      </select>
    </>
  );
}

数行のコードでフィルタリングを実装することができました!
同じ概念を使用して、TodoListStatsコンポーネントを実装します。

次の統計を表示します。

  • todo項目の合計数
  • 完了項目の合計数
  • 未完了項目の総数
  • 達成率

統計情報ごとにselectorを作成することもできますが、より簡単な方法は、必要なデータを含むオブジェクトを返すselectorを1つ作成することです。このselectorをdoListStatsStateと呼びます。

const todoListStatsState = selector({
  key: 'todoListStatsState',
  get: ({get}) => {
    const todoList = get(todoListState);
    const totalNum = todoList.length;
    const totalCompletedNum = todoList.filter((item) => item.isComplete).length;
    const totalUncompletedNum = totalNum - totalCompletedNum;
    const percentCompleted = totalNum === 0 ? 0 : totalCompletedNum / totalNum;

    return {
      totalNum,
      totalCompletedNum,
      totalUncompletedNum,
      percentCompleted,
    };
  },
});

todoListStatsStateの値を読み取るには、もう一度useRecoilValue()を使用します。

function TodoListStats() {
  const {
    totalNum,
    totalCompletedNum,
    totalUncompletedNum,
    percentCompleted,
  } = useRecoilValue(todoListStatsState);

  const formattedPercentCompleted = Math.round(percentCompleted * 100);

  return (
    <ul>
      <li>Total items: {totalNum}</li>
      <li>Items completed: {totalCompletedNum}</li>
      <li>Items not completed: {totalUncompletedNum}</li>
      <li>Percent completed: {formattedPercentCompleted}</li>
    </ul>
  );
}

まとめると、私たちはすべての要件を満たすtodoリストアプリを作成しました。

  • todo項目を追加する
  • todo項目を編集する
  • todo項目を削除する
  • todo項目をフィルタする
  • 有用な統計を表示

参考サイト

公式ドキュメント
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳⑦ 基本チュートリアル-Selectors

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


Selector

selectorは、divider state (派生状態)を表します。divider stateは、与えられたstateを何らかの方法で変更する純粋な関数にstateを渡す出力と考えることができます。

派生stateは、他のデータに依存する動的データを構築できるため、強力な概念です。todoリストアプリケーションのコンテキストでは、次のものが派生stateと見なされます。

  • フィルタされたtodoリスト:いくつかの基準(すでに完了している項目を除外するなど)に基づいてフィルタされた特定の項目を持つ新しいリストを作成することによって、完全なtodoリストから派生します。

  • ToDoリストの統計:リスト内の項目の総数、完了した項目の数、完了した項目の割合など、リストの有用な属性を計算することによって、完全なToDoリストから得られます。

フィルタされたtodoリストを実装するには、atomに値を保存できる一連のフィルタ条件を選択する必要があります。
使用するフィルタオプションは、「すべて表示」、「完了を表示」、および「未完了を表示」です。デフォルト値は「すべて表示」です。

const todoListFilterState = atom({
  key: 'todoListFilterState',
  default: 'Show All',
});

todoListFilterStatetodoListStateを使用して、フィルタされたリストを導出するfilteredTodoListStateselectorを構築できます。

const filteredTodoListState = selector({
  key: 'filteredTodoListState',
  get: ({get}) => {
    const filter = get(todoListFilterState);
    const list = get(todoListState);

    switch (filter) {
      case 'Show Completed':
        return list.filter((item) => item.isComplete);
      case 'Show Uncompleted':
        return list.filter((item) => !item.isComplete);
      default:
        return list;
    }
  },
});

filteredTodoListStateは内部的に2つの依存関係 (todoListFilterStatetodoListState) を追跡し、どちらかが変更された場合に再実行されるようにします。

コンポーネントの観点から見ると、selectorは、atomを読み取るために使用されるのと同じhookを使用して読み取ることができます。ただし、一部のhookは書き込み可能なstate(i.e useRecoilState())でのみ機能することに注意してください。
全てのatomは書き込み可能stateであるが、書き込み可能stateとみなされるのは一部のselectorのみである(getプロパティとsetプロパティの両方を持つselector)。このトピックの詳細は、コアコンセプトを参照してください。

フィルタリングされたtodoListの表示は、TodoListコンポーネントで1行変更するだけです。

function TodoList() {
  // changed from todoListState to filteredTodoListState
  const todoList = useRecoilValue(filteredTodoListState);

  return (
    <>
      <TodoListStats />
      <TodoListFilters />
      <TodoItemCreator />

      {todoList.map((todoItem) => (
        <TodoItem item={todoItem} key={todoItem.id} />
      ))}
    </>
  );
}

todoListFilterStateにデフォルト値「すべて表示(Show All)」が指定されているため、UIはすべてのtodoを表示していることに注意してください。
フィルタを変更するには、TodoListFiltersコンポーネントを実装する必要があります。

function TodoListFilters() {
  const [filter, setFilter] = useRecoilState(todoListFilterState);

  const updateFilter = ({target: {value}}) => {
    setFilter(value);
  };

  return (
    <>
      Filter:
      <select value={filter} onChange={updateFilter}>
        <option value="Show All">All</option>
        <option value="Show Completed">Completed</option>
        <option value="Show Uncompleted">Uncompleted</option>
      </select>
    </>
  );
}

数行のコードでフィルタリングを実装することができました!
同じ概念を使用して、TodoListStatsコンポーネントを実装します。

次の統計を表示します。

  • todo項目の合計数
  • 完了項目の合計数
  • 未完了項目の総数
  • 達成率

統計情報ごとにselectorを作成することもできますが、より簡単な方法は、必要なデータを含むオブジェクトを返すselectorを1つ作成することです。このselectorをdoListStatsStateと呼びます。

const todoListStatsState = selector({
  key: 'todoListStatsState',
  get: ({get}) => {
    const todoList = get(todoListState);
    const totalNum = todoList.length;
    const totalCompletedNum = todoList.filter((item) => item.isComplete).length;
    const totalUncompletedNum = totalNum - totalCompletedNum;
    const percentCompleted = totalNum === 0 ? 0 : totalCompletedNum / totalNum;

    return {
      totalNum,
      totalCompletedNum,
      totalUncompletedNum,
      percentCompleted,
    };
  },
});

todoListStatsStateの値を読み取るには、もう一度useRecoilValue()を使用します。

function TodoListStats() {
  const {
    totalNum,
    totalCompletedNum,
    totalUncompletedNum,
    percentCompleted,
  } = useRecoilValue(todoListStatsState);

  const formattedPercentCompleted = Math.round(percentCompleted * 100);

  return (
    <ul>
      <li>Total items: {totalNum}</li>
      <li>Items completed: {totalCompletedNum}</li>
      <li>Items not completed: {totalUncompletedNum}</li>
      <li>Percent completed: {formattedPercentCompleted}</li>
    </ul>
  );
}

まとめると、私たちはすべての要件を満たすtodoリストアプリを作成しました。

  • todo項目を追加する
  • todo項目を編集する
  • todo項目を削除する
  • todo項目をフィルタする
  • 有用な統計を表示

参考サイト

公式ドキュメント
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳⑥ Atoms

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

  • 前書き
  • 基本チュートリアル
  • ガイド
  • APIリファレンス

全目次は一番下にあります


Atom

atomには、アプリケーションstateの信頼できる情報源(source)が含まれています。
このtodoリストでは、sourceはオブジェクトの配列であり、各オブジェクトはtodo項目を表します。

リストatomをtodoListStateと呼び出し、atom()関数を使用して作成します。

const todoListState = atom({
  key: 'todoListState',
  default: [],
});

atomに一意のkeyを与え、デフォルト値を空の配列に設定します。
このatomの内容を読み取るには、TodoListコンポーネントのuseRecoilValue()hookを使用します。

function TodoList() {
  const todoList = useRecoilValue(todoListState);

  return (
    <>
      {/* <TodoListStats /> */}
      {/* <TodoListFilters /> */}
      <TodoItemCreator />

      {todoList.map((todoItem) => (
        <TodoItem key={todoItem.id} item={todoItem} />
      ))}
    </>
  );
}

コメントアウトされたコンポーネントは、次のセクションで実装されます。

新しいtodo項目を作成するには、todoListStateの内容を更新する設定関数にアクセスする必要があります。
useSetRecoilState()hookを使用して、TodoItemCreatorコンポーネントに設定関数を取得できます。

function TodoItemCreator() {
  const [inputValue, setInputValue] = useState('');
  const setTodoList = useSetRecoilState(todoListState);

  const addItem = () => {
    setTodoList((oldTodoList) => [
      ...oldTodoList,
      {
        id: getId(),
        text: inputValue,
        isComplete: false,
      },
    ]);
    setInputValue('');
  };

  const onChange = ({target: {value}}) => {
    setInputValue(value);
  };

  return (
    <div>
      <input type="text" value={inputValue} onChange={onChange} />
      <button onClick={addItem}>Add</button>
    </div>
  );
}

// utility for creating unique Id
let id = 0;
function getId() {
  return id++;
}

古いtodoリストに基づいて新しいtodoリストを作成できるように、設定関数のupdater形式を使用していることに注意してください。

TodoItemコンポーネントは、todo項目の値を表示しますが、そのテキストを変更したり項目を削除したりすることもできます。todoListStateを読み取って、項目テキストを更新し、完了としてマークし、削除するために使用する設定関数を取得するには、useRecoilState()を使用します。

function TodoItem({item}) {
  const [todoList, setTodoList] = useRecoilState(todoListState);
  const index = todoList.findIndex((listItem) => listItem === item);

  const editItemText = ({target: {value}}) => {
    const newList = replaceItemAtIndex(todoList, index, {
      ...item,
      text: value,
    });

    setTodoList(newList);
  };

  const toggleItemCompletion = () => {
    const newList = replaceItemAtIndex(todoList, index, {
      ...item,
      isComplete: !item.isComplete,
    });

    setTodoList(newList);
  };

  const deleteItem = () => {
    const newList = removeItemAtIndex(todoList, index);

    setTodoList(newList);
  };

  return (
    <div>
      <input type="text" value={item.text} onChange={editItemText} />
      <input
        type="checkbox"
        checked={item.isComplete}
        onChange={toggleItemCompletion}
      />
      <button onClick={deleteItem}>X</button>
    </div>
  );
}

function replaceItemAtIndex(arr, index, newValue) {
  return [...arr.slice(0, index), newValue, ...arr.slice(index + 1)];
}

function removeItemAtIndex(arr, index) {
  return [...arr.slice(0, index), ...arr.slice(index + 1)];
}

これで、完全に機能するToDoリストができました!
次のセクションでは、selectorを使用してリストを次のレベルアップする方法について説明します。


参考サイト

公式ドキュメント
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳⑥ 基本チュートリアル-Atoms

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


Atom

atomには、アプリケーションstateの信頼できる情報源(source)が含まれています。
このtodoリストでは、sourceはオブジェクトの配列であり、各オブジェクトはtodo項目を表します。

リストatomをtodoListStateと呼び出し、atom()関数を使用して作成します。

const todoListState = atom({
  key: 'todoListState',
  default: [],
});

atomに一意のkeyを与え、デフォルト値を空の配列に設定します。
このatomの内容を読み取るには、TodoListコンポーネントのuseRecoilValue()hookを使用します。

function TodoList() {
  const todoList = useRecoilValue(todoListState);

  return (
    <>
      {/* <TodoListStats /> */}
      {/* <TodoListFilters /> */}
      <TodoItemCreator />

      {todoList.map((todoItem) => (
        <TodoItem key={todoItem.id} item={todoItem} />
      ))}
    </>
  );
}

コメントアウトされたコンポーネントは、次のセクションで実装されます。

新しいtodo項目を作成するには、todoListStateの内容を更新する設定関数にアクセスする必要があります。
useSetRecoilState()hookを使用して、TodoItemCreatorコンポーネントに設定関数を取得できます。

function TodoItemCreator() {
  const [inputValue, setInputValue] = useState('');
  const setTodoList = useSetRecoilState(todoListState);

  const addItem = () => {
    setTodoList((oldTodoList) => [
      ...oldTodoList,
      {
        id: getId(),
        text: inputValue,
        isComplete: false,
      },
    ]);
    setInputValue('');
  };

  const onChange = ({target: {value}}) => {
    setInputValue(value);
  };

  return (
    <div>
      <input type="text" value={inputValue} onChange={onChange} />
      <button onClick={addItem}>Add</button>
    </div>
  );
}

// 一意のIDを作成するためのユーティリティ
let id = 0;
function getId() {
  return id++;
}

古いtodoリストに基づいて新しいtodoリストを作成できるように、設定関数のupdater形式を使用していることに注意してください。

TodoItemコンポーネントは、todo項目の値を表示しますが、そのテキストを変更したり項目を削除したりすることもできます。todoListStateを読み取って、項目テキストを更新し、完了としてマークし、削除するために使用する設定関数を取得するには、useRecoilState()を使用します。

function TodoItem({item}) {
  const [todoList, setTodoList] = useRecoilState(todoListState);
  const index = todoList.findIndex((listItem) => listItem === item);

  const editItemText = ({target: {value}}) => {
    const newList = replaceItemAtIndex(todoList, index, {
      ...item,
      text: value,
    });

    setTodoList(newList);
  };

  const toggleItemCompletion = () => {
    const newList = replaceItemAtIndex(todoList, index, {
      ...item,
      isComplete: !item.isComplete,
    });

    setTodoList(newList);
  };

  const deleteItem = () => {
    const newList = removeItemAtIndex(todoList, index);

    setTodoList(newList);
  };

  return (
    <div>
      <input type="text" value={item.text} onChange={editItemText} />
      <input
        type="checkbox"
        checked={item.isComplete}
        onChange={toggleItemCompletion}
      />
      <button onClick={deleteItem}>X</button>
    </div>
  );
}

function replaceItemAtIndex(arr, index, newValue) {
  return [...arr.slice(0, index), newValue, ...arr.slice(index + 1)];
}

function removeItemAtIndex(arr, index) {
  return [...arr.slice(0, index), ...arr.slice(index + 1)];
}

これで、完全に機能するToDoリストができました!
次のセクションでは、selectorを使用してリストを次のレベルアップする方法について説明します。


>>Demoを作りました


参考サイト

公式ドキュメント
みらい翻訳
Demoのリポジトリ


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳⑤ 概要

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

  • 前書き
  • 基本チュートリアル
  • ガイド
  • APIリファレンス

全目次は一番下にあります


概要

このセクション(基本チュートリアル)では、RecoilとReactがインストールされていることを前提としています。
RecoilとReactをゼロから始める方法については、入門を参照してください。
以下のセクションのコンポーネントは、親ツリーに<RecoilRoot />があるものとします。

このチュートリアルでは、単純なToDoリストアプリケーションを作成します。
私たちのアプリは以下のことができます。

  • todo項目を追加する
  • todo項目を編集する
  • todo項目を削除する
  • todo項目をフィルタする
  • 有用な統計を表示

その過程で、atom、selector、atom families、そしてRecoil APIによって公開されるhooksについて説明します。


参考サイト

公式ドキュメント
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳⑤ 基本チュートリアル-概要

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


概要

このセクション(基本チュートリアル)では、RecoilとReactがインストールされていることを前提としています。
RecoilとReactをゼロから始める方法については、入門を参照してください。
以下のセクションのコンポーネントは、親ツリーに<RecoilRoot />があるものとします。

このチュートリアルでは、単純なToDoリストアプリケーションを作成します。
私たちのアプリは以下のことができます。

  • todo項目を追加する
  • todo項目を編集する
  • todo項目を削除する
  • todo項目をフィルタする
  • 有用な統計を表示

その過程で、atom、selector、atom families、そしてRecoil APIによって公開されるhooksについて説明します。


参考サイト

公式ドキュメント
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React/Redux初心者が参考にしたい教材集

はじめに

業務でReact/Reduxを使うことになったものの、キャッチアップコストが高い割りに初心者向けの書籍はあまり世に出てない印象を受けました。
そこで自分が参考にした教材たちを書き残しておきたいと思います。

最初の一歩

progate

安定のprogate先輩。ハマりがちな環境構築もないので、まずはこちらでReactに触れてみるのが良いでしょう。(要課金)
JSに不安のある方は合わせてES2015も合わせてやっておくと吉。
https://prog-8.com/languages/react

ReactでReduxを使ってみよう Kindle版

Reduxについて初心者向けに1行1行説明してくれておりわかりやすいです。
https://www.amazon.co.jp/dp/B07P7DBLBL/ref=cm_sw_em_r_mt_dp_4nLJFbGJCPMD7

慣れてきたら

最短で学ぶReactとReduxの基礎から実践まで

ライブラリやAPIを使いながらReact+Reduxで動く物を作れますし、説明もわかりやすいです。ただ、若干古めな教材なので環境構築で少し手こずりました。(JSはほんと移り変わりが早いですね)
https://www.udemy.com/share/101YJ4AEAZdV5TTHkH/

【はむ式】フロントエンドエンジニアのための React ・ Redux アプリケーション開発入門

こちらも一通りのものを作れますが、「最短で学ぶReactとReduxの基礎から実践まで」よりはちょっと難しい印象です。
https://www.udemy.com/share/1021hGAEAZdV5TTHkH/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React④】Props

Propsとは

  • Propsとはコンポネントの属性、あるデータの属性で参照できるもののこと
  • {}で囲って渡していく
    • 受けわたせるデータ型は文字列、数値、真偽、配列、オブジェクト、変数などなんでも
    • 文字列は{}なしでもok
  • 例えばUserのComponentに対してnameというPropsを与えることができる

keyの指定

ReactではバーチャルDOMでどのDOMが変更されたかを管理し、変更点のみ実際のDOMに反映している。key={index}のようにそれぞれのDOMにkeyを与えてあげることで必要最低限なDOM範囲を管理している

//エラー文
array,iterator should have a unique "key" prop.
import React from 'react';

const App = () =>{
    const profiles = [
        { name:"Taro", age:10 }, 
        { name:"Hanako", age: 5 },
        { name:"Noname" }
    ]

    return (
      <div>
      {
        profiles.map((profile,index) => {
          return <User name={profile.name} age={profile.age} key={index}/>
        })
      }
      </div>
    )
  }

  //外からの入力を参照して画面に出力することができる
  const User = (props) =>{
    return <div>Hi!, I am {props.name},and {props.age} years old! </div>
  }

  //ageが入力されなかったときにage1がデフォルト値として1が渡される
  User.defaultProps ={
    age:1 
  }

Propsでデータを受け渡す

親コンポーネントから子コンポーネントにPropsデータを受け渡す。

Blog.jsx
//親コンポーネント
import React from 'React';
import Article from "./Article";

//title={"React"} が子コンポーネントに受け渡される
class Blog extends React.Component{
    constructor(props){
        super(props);
    }
    render(){
        return(
            <>
            <Article title={"React"} />  
            </>
        )
    }
}

export default Blog
Article.jsx
import React from 'React';

const Article = (props) =>{
    return(
        <div>
            <h2>{props.title}</h2>
        </div>
    )
};

export default Article

いろんな型のデータを渡す

子コンポーネントに以下を渡します
title={"React"}order={3}isPublished={true}author={"authorName"}

Blog.jsx
import React from 'React';
import Article from "./Article";

class Blog extends React.Component{
    constructor(props){
        super(props);
    }
    render(){
        const authorName = "Facebook";
        return(
            <>
              <Article 
                title={"React"} 
                order={3} 
                isPublished={true} 
                author={"authorName"} 
              />  
            </>
        )
    }
}
export default Blog
Article.jsx
import React from 'React';

const Article = (props) =>{
    let publishState ="";
    if (props.isPublished){
        publishState = "公開"
    }else{
        publishState = "非公開"
    } 
    return(
        <div>
            <h2>{props.title}</p>
            <p>順番:{props.order}</p>
            <p>著者:{props.author}</p>
            <p>{publishState}</p>
        </div>
    )
};

export default Article

再利用する

Blog.jsx
import React from 'React';
import Article from "./Article";

class Blog extends React.Component{
    constructor(props){
        super(props);
    }
    render(){
        const authorName = "Facebook";
        return(
            <>
              <Article title={"React"} />  
              <Article title={"JSX"} />  
              <Article title={"Component"} />  
              <Article title={"Props"} />  
            </>
        )
    }
}
export default Blog
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React③】Component

Componentとは

ComponentはUIを作成するためにあり、見た目(View)機能(Controller)で成り立っている。
webの構造はComponentのツリー構造をしていて
headerのComponentのなかにnavigation、login のComponentが含まれる。
ReactではComponentを一個ずつ作ってWebアプリなどを構成する。

Componentのメリット

  • 再利用性
    • 一つのComponentを作ると引数(Props)を渡すことができる
    • 例:buttonというコンポネントからlogin、log-outボタンを作成できる
  • 分割管理
    • Component同士は疎結合なので、影響し合わない
  • 修正変更、新機能追加が簡単
    • 疎結合であることから、修正変更が必要なComponentのみ変更することができる

Componentの種類

  • Class Component:クラスによって定義されたComponent
    • React.Componentを継承
    • constructorでpropsを初期化
    • ライフサイクルやstateを持つ
      • webページが表示されるときに生成され、ユーザの操作や次のページへの遷移すると消える
    • propsにはthisが必要(このclass内のpropsを使うため)
    • render内でJSXをreturn
    • 最近推奨されてない
//App=Class Component

import React, { Component } from 'react';

class App extends Component{
    constructor(props){
        super(props);
    }
    render() {
        return(
            <div>
                <h2>{this.props.title}</h2>
            </div>
        );
    }
}
  • Functional Component:関数型で定義されたComponent
    • ES6のアロー関数で記述
    • stateを持たない
    • propsを引数に受け取ることができる 
    • JSXをreturnする
//App=Functional Component

import React from 'react';
//Functional Componentでは{Component}のimportは不要

const App = (props) =>{
    return (
        <div>
            <h2>{props.title}</h2>
        </div>
    );  
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳④ 前書き-入門

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


入門

Create React App

RecoilはReactの状態管理ライブラリであるため、Recoilを使用するには、Reactをインストールして実行する必要があります。Reactアプリケーションをブートストラップするための最も簡単で推奨される方法は、Create React Appを使用することです。

npx create-react-app my-app

npxはnpm5.2以降に付属するパッケージランナーツールです。古いnpmバージョンの手順を参照してください。

Create React Appをインストールするその他の方法については、公式ドキュメントを参照してください。

Installation

Recoilパッケージはnpmにあります。
最新の安定バージョンをインストールするには、次のコマンドを実行します。

npm install recoil

yarnを使用している場合:

yarn add recoil

RecoilRoot

Recoil State を使用するコンポーネントでは、親ツリーのどこかにRecoilRootが表示される必要があります。
これはルートコンポーネントに置くとよいでしょう。

import React from 'react';
import {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';

function App() {
  return (
    <RecoilRoot>
      <CharacterCounter />
    </RecoilRoot>
  );
}

次のセクションでは、CharacterCounterコンポーネントを実装します。

Atom

Atomはstateを表し、任意のコンポーネントから読み取りおよび書き込みを行うことができます。
Atomの値を読み取るコンポーネントは暗黙的にそのAtomに登録されているため、Atomを更新すると、そのAtomに登録されているすべてのコンポーネントが再レンダリングされます。

const textState = atom({
  key: 'textState', // unique ID (他の atoms/selectors に関して)
  default: '', // default value (初期値として)
});

Atomからの読み取りとAtomへの書き込みが必要なコンポーネントは、useRecoilState()以下に示すように使用する必要があります。

function CharacterCounter() {
  return (
    <div>
      <TextInput />
      <CharacterCount />
    </div>
  );
}

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
      Echo: {text}
    </div>
  );
}

Selector

Selectorは、派生状態(derived state)を表します。派生stateは state の変換を行います。
指定された状態を何らかの方法で変換する純粋関数に状態を渡す出力と考えることができます。

const charCountState = selector({
  key: 'charCountState', // unique ID (他の atoms/selectors に関して)
  get: ({get}) => {
    const text = get(textState);

    return text.length;
  },
});

useRecoilValue()フックを使用して、charCountStateの値を読み取ることができます。

function CharacterCount() {
  const count = useRecoilValue(charCountState);

  return <>Character Count: {count}</>;
}

画面収録-2020-10-19-22.18.02.gif

>>作ってみました


参考サイト

公式ドキュメント
Create React App
npx
古いnpmバージョンの手順
npm
yarn
Pure function (純粋関数)とは
みらい翻訳
Demoのリポジトリ ディレクトリ構成の参考に(なるかわかりませんが)どうぞ


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳④ 入門

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


入門

Create React App

RecoilはReactの状態管理ライブラリであるため、Recoilを使用するには、Reactをインストールして実行する必要があります。Reactアプリケーションをブートストラップするための最も簡単で推奨される方法は、Create React Appを使用することです。

npx create-react-app my-app

npxはnpm5.2以降に付属するパッケージランナーツールです。古いnpmバージョンの手順を参照してください。

Create React Appをインストールするその他の方法については、公式ドキュメントを参照してください。

Installation

Recoilパッケージはnpmにあります。
最新の安定バージョンをインストールするには、次のコマンドを実行します。

npm install recoil

yarnを使用している場合:

yarn add recoil

RecoilRoot

Recoil State を使用するコンポーネントでは、親ツリーのどこかにRecoilRootが表示される必要があります。
これはルートコンポーネントに置くとよいでしょう。

import React from 'react';
import {
  RecoilRoot,
  atom,
  selector,
  useRecoilState,
  useRecoilValue,
} from 'recoil';

function App() {
  return (
    <RecoilRoot>
      <CharacterCounter />
    </RecoilRoot>
  );
}

次のセクションでは、CharacterCounterコンポーネントを実装します。

Atom

Atomはstateを表し、任意のコンポーネントから読み取りおよび書き込みを行うことができます。
Atomの値を読み取るコンポーネントは暗黙的にそのAtomに登録されているため、Atomを更新すると、そのAtomに登録されているすべてのコンポーネントが再レンダリングされます。

const textState = atom({
  key: 'textState', // unique ID (他の atoms/selectors に関して)
  default: '', // default value (初期値として)
});

Atomからの読み取りとAtomへの書き込みが必要なコンポーネントは、useRecoilState()以下に示すように使用する必要があります。

function CharacterCounter() {
  return (
    <div>
      <TextInput />
      <CharacterCount />
    </div>
  );
}

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
      Echo: {text}
    </div>
  );
}

Selector

Selectorは、derived state(派生状態?)を表します。derived statestateの変換です。
指定された状態を何らかの方法で変換する純粋関数に状態を渡す出力と考えることができます。

const charCountState = selector({
  key: 'charCountState', // unique ID (他の atoms/selectors に関して)
  get: ({get}) => {
    const text = get(textState);

    return text.length;
  },
});

useRecoilValue()フックを使用して、charCountStateの値を読み取ることができます。

function CharacterCount() {
  const count = useRecoilValue(charCountState);

  return <>Character Count: {count}</>;
}

画面収録-2020-10-19-22.18.02.gif


参考サイト

公式ドキュメント
Create React App
npx
古いnpmバージョンの手順
npm
yarn
Pure function (純粋関数)とは
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳③

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次


インストール

NPM

Recoilパッケージはnpmyarnにあります。
最新の安定版をインストールするには、次のコマンドを実行します。

npmを使用している場合:

npm install recoil

yarnを使用している場合:

yarn add recoil

Bundler

NPMを介してインストールされたRecoilは、WebpackRollupなどのモジュールバンドラーとうまく組み合わせられます。

ES 5サポート

RecoilビルドはES 5にトランスパイルされず、ES 5でのRecoilの使用はサポートされていません。
ES 6を基本として提供していないブラウザをサポートする必要がある場合は、Babelでコードをコンパイルし、preset@babel/preset-envを使用してください。
ただし、これはサポートされていないため、問題が発生する可能性があります。

特に、Reactと同様に、Recoilは、ES 6のMapSetのタイプやその他の機能に依存します。polyfillsを使用してこれらの機能をエミュレートすると、パフォーマンスが大幅に低下する可能性があります。

CDN

バージョン0.0 .11以降、Recoilは<script>タグで直接使用できるUMDビルドを提供し、シンボルRecoilをグローバルネームスペースに公開しています。新しいバージョンからの予期しない破損を避けるために、特定のバージョン番号とビルドにリンクすることをお勧めします。

<script src="https://cdn.jsdelivr.net/npm/recoil@0.0.11/umd/recoil.production.js"></script>

CDN上のすべてのRecoilファイルは、jsdelivrで参照できます。

ESLint

プロジェクトでeslin-plugin-react-hooksを使用している場合。たとえば、次のようなeslint設定では、


// previous .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

additionalHooksのリストに'useRecoilCallback'を追加することをお勧めします。
この変更により、ESLintはuseRecoilCallback()に渡された依存関係が誤って指定された場合に警告を出し、修正を提案します。
additionalHooksのフォーマットは正規表現の文字列です。

// modified .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": [
      "warn", {
        "additionalHooks": "useRecoilCallback"
      }
    ]
  }
}

参考サイト

公式ドキュメント
npm
yarn
Webpack
Rollup
Babel
preset@babel/preset-env
jsdelivr
eslin-plugin-react-hooks
useRecoilCallback
みらい翻訳


全目次

  • 前書き
  • 基本チュートリアル
    • イントロ
    • Atoms
    • Selectors
  • ガイド
    • 非同期データクエリ
    • 非同期状態(state)同期
    • 状態(state)の永続性
  • APIリファレンス
    • Core
    • 実用(utils)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳③ 前書き-インストール

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


インストール

NPM

Recoilパッケージはnpmにあります。
最新の安定版をインストールするには、次のコマンドを実行します。

npm install recoil

yarnを使用している場合:

yarn add recoil

Bundler

NPMを介してインストールされたRecoilは、WebpackRollupなどのモジュールバンドラーとうまく組み合わせられます。

ES 5サポート

RecoilビルドはES 5にトランスパイルされず、ES 5でのRecoilの使用はサポートされていません。
ES 6を基本として提供していないブラウザをサポートする必要がある場合は、Babelでコードをコンパイルし、preset@babel/preset-envを使用してください。
ただし、これはサポートされていないため、問題が発生する可能性があります。

特に、Reactと同様に、Recoilは、ES 6のMapSetのタイプやその他の機能に依存します。polyfillsを使用してこれらの機能をエミュレートすると、パフォーマンスが大幅に低下する可能性があります。

CDN

バージョン0.0 .11以降、Recoilは<script>タグで直接使用できるUMDビルドを提供し、シンボルRecoilをグローバルネームスペースに公開しています。新しいバージョンからの予期しない破損を避けるために、特定のバージョン番号とビルドにリンクすることをお勧めします。

<script src="https://cdn.jsdelivr.net/npm/recoil@0.0.11/umd/recoil.production.js"></script>

CDN上のすべてのRecoilファイルは、jsdelivrで参照できます。

ESLint

プロジェクトでeslint-plugin-react-hooksを使用している場合。たとえば、次のようなeslint設定では、

// previous .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

additionalHooksのリストに'useRecoilCallback'を追加することをお勧めします。
この変更により、ESLintはuseRecoilCallback()に渡された依存関係が誤って指定された場合に警告を出し、修正を提案します。
additionalHooksのフォーマットは正規表現の文字列です。

// modified .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": [
      "warn", {
        "additionalHooks": "useRecoilCallback"
      }
    ]
  }
}

参考サイト

公式ドキュメント
npm
yarn
Webpack
Rollup
Babel
preset@babel/preset-env
jsdelivr
eslint-plugin-react-hooks
useRecoilCallback
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳③ インストール

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


インストール

NPM

Recoilパッケージはnpmにあります。
最新の安定版をインストールするには、次のコマンドを実行します。

npm install recoil

yarnを使用している場合:

yarn add recoil

Bundler

NPMを介してインストールされたRecoilは、WebpackRollupなどのモジュールバンドラーとうまく組み合わせられます。

ES 5サポート

RecoilビルドはES 5にトランスパイルされず、ES 5でのRecoilの使用はサポートされていません。
ES 6を基本として提供していないブラウザをサポートする必要がある場合は、Babelでコードをコンパイルし、preset@babel/preset-envを使用してください。
ただし、これはサポートされていないため、問題が発生する可能性があります。

特に、Reactと同様に、Recoilは、ES 6のMapSetのタイプやその他の機能に依存します。polyfillsを使用してこれらの機能をエミュレートすると、パフォーマンスが大幅に低下する可能性があります。

CDN

バージョン0.0 .11以降、Recoilは<script>タグで直接使用できるUMDビルドを提供し、シンボルRecoilをグローバルネームスペースに公開しています。新しいバージョンからの予期しない破損を避けるために、特定のバージョン番号とビルドにリンクすることをお勧めします。

<script src="https://cdn.jsdelivr.net/npm/recoil@0.0.11/umd/recoil.production.js"></script>

CDN上のすべてのRecoilファイルは、jsdelivrで参照できます。

ESLint

プロジェクトでeslint-plugin-react-hooksを使用している場合。たとえば、次のようなeslint設定では、

// previous .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

additionalHooksのリストに'useRecoilCallback'を追加することをお勧めします。
この変更により、ESLintはuseRecoilCallback()に渡された依存関係が誤って指定された場合に警告を出し、修正を提案します。
additionalHooksのフォーマットは正規表現の文字列です。

// modified .eslint config
{
  "plugins": [
    "react-hooks"
  ],
  "rules": {
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": [
      "warn", {
        "additionalHooks": "useRecoilCallback"
      }
    ]
  }
}

参考サイト

公式ドキュメント
npm
yarn
Webpack
Rollup
Babel
preset@babel/preset-env
jsdelivr
eslint-plugin-react-hooks
useRecoilCallback
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳②

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次


コアコンセプト

概要

Recoilを使用すると、atom(共有state)からselector(純粋関数)を通ってReactコンポーネントに流れるデータフローグラフを作成できます。
atomは、コンポーネントが登録できるstateの単位です。selectorは、このstateを同期的または非同期的に変換します。

Atoms

atomはstateの単位です。
atomが更新されると、登録された各コンポーネントが新しい値で再描画されます。実行時にも作成できます。[React local component state] の代わりにatomを使用できます。同じatomが複数のコンポーネントから使用されている場合、それらのコンポーネントはすべてstateを共有します。

atomは、atom関数を使用して作成されます。

const fontSizeState = atom({
  key: 'fontSizeState',
  default: 14,
});

atomには一意のkeyが必要で、これはデバッグ、永続化、およびすべてのatomのマップを表示できる特定の高度なAPIに使用されます。
2つのatomが同じkeyを持つとエラーになるで、それらがグローバルに一意であることを確認してください。コンポーネントのstateと同様に、既定値もあります。

コンポーネントからatomを読み書きするには、useRecoilStateというHookを使用します。ReactのuseStateに似ているが、コンポーネント間でstateを共有できるようになります。

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return (
    <button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
      Click to Enlarge
    </button>
  );
}

ボタンをクリックすると、ボタンのフォントサイズが1つ大きくなります。
他のコンポーネントでも同じフォントサイズを使用できるようになりました。

function Text() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return <p style={{fontSize}}>This text will increase in size too.</p>;
}

Selectors

selectorは、atomやその他のselectorを入力として受け付ける純粋な関数です。
これらの上流のatomまたはselectorが更新されると、selector関数が再評価されます。コンポーネントはatomと同じようにselectorに登録でき、selectorが変更されると再レンダリングされます。

selectorは、stateに基づく派生データを計算するために使用されます。これにより冗長なstateを避けることができ、通常はreducerがstateを同期させて有効に保つ必要がなくなります。その代わりに、stateの最小セットはatomに格納され、それ以外はすべて、その最小stateの関数として効率的に計算されます。selectorは、どのコンポーネントが必要とし、どのstateに依存しているかを追跡するので、この機能的なアプローチがより効率的になります。

構成要素の観点から見ると、selectorとatomは同じ境界面を有するため、互いに置換することができます。

selectorは、selector関数を使用して定義します。

const fontSizeLabelState = selector({
  key: 'fontSizeLabelState',
  get: ({get}) => {
    const fontSize = get(fontSizeState);
    const unit = 'px';

    return `${fontSize}${unit}`;
  },
});

getプロパティは、計算される関数です。渡されたget引数を使用して、atomやその他のselectorの値にアクセスできます。別のatomまたはselectorにアクセスすると、依存関係が作成され、別のatomまたはselectorを更新すると、このatomまたはselectorが再計算されます。

このfontSizeLabelStateの例では、selectorにはfontSizeState atomという1つの依存関係があります。
概念的には、fontSizeLabelState selectorはfontSizeStateを入力として受け取り、フォーマットされたフォントサイズラベルを出力として返す純粋な関数のように動作します。

selectorは、useRecoilValue()を使用して読み取ることができます。
これは、atomまたはselectorを引数として取り、対応する値を返します。fontSizeLabelState selectorが書き込み可能ではないため、useRecoilState()は使用しません。
(書き込み可能selectorの詳細については、selectorAPIリファレンスを参照してください。)

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  const fontSizeLabel = useRecoilValue(fontSizeLabelState);

  return (
    <>
      <div>Current font size: ${fontSizeLabel}</div>

      <button onClick={() => setFontSize(fontSize + 1)} style={{fontSize}}>
        Click to Enlarge
      </button>
    </>
  );
}

ボタンをクリックすると、ボタンのフォントサイズが大きくなり、現在のフォントサイズを反映するようにフォントサイズのラベルが更新されます。


参考サイト

公式ドキュメント
Pure function (純粋関数)とは
みらい翻訳


全目次

  • 前書き
  • 基本チュートリアル
    • イントロ
    • Atoms
    • Selectors
  • ガイド
    • 非同期データクエリ
    • 非同期状態(state)同期
    • 状態(state)の永続性
  • APIリファレンス
    • Core
    • 実用(utils)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳② 前書き-コアコンセプト

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


コアコンセプト

概要

Recoilを使用すると、atom(共有state)からselector(純粋関数)を通ってReactコンポーネントに流れるデータフローグラフを作成できます。
atomは、コンポーネントが登録できるstateの単位です。selectorは、このstateを同期的または非同期的に変換します。

Atoms

atomはstateの単位です。
atomが更新されると、登録された各コンポーネントが新しい値で再描画されます。実行時にも作成できます。[React local component state] の代わりにatomを使用できます。同じatomが複数のコンポーネントから使用されている場合、それらのコンポーネントはすべてstateを共有します。

atomは、atom関数を使用して作成されます。

const fontSizeState = atom({
  key: 'fontSizeState',
  default: 14,
});

atomには一意のkeyが必要で、これはデバッグ、永続化、およびすべてのatomのマップを表示できる特定の高度なAPIに使用されます。
2つのatomが同じkeyを持つとエラーになるで、それらがグローバルに一意であることを確認してください。コンポーネントのstateと同様に、既定値もあります。

コンポーネントからatomを読み書きするには、useRecoilStateというHookを使用します。ReactのuseStateに似ているが、コンポーネント間でstateを共有できるようになります。

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return (
    <button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
      Click to Enlarge
    </button>
  );
}

ボタンをクリックすると、ボタンのフォントサイズが1つ大きくなります。
他のコンポーネントでも同じフォントサイズを使用できるようになりました。

function Text() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return <p style={{fontSize}}>This text will increase in size too.</p>;
}

Selectors

selectorは、atomやその他のselectorを入力として受け付ける純粋な関数です。
これらの上流のatomまたはselectorが更新されると、selector関数が再評価されます。
コンポーネントはatomと同じようにselectorに登録でき、selectorが変更されると再レンダリングされます。

selectorは、stateに基づく派生データを計算するために使用されます。これにより冗長なstateを避けることができ、通常はreducerがstateを同期させて有効に保つ必要がなくなります。その代わりに、stateの最小セットはatomに格納され、それ以外はすべて、その最小stateの関数として効率的に計算されます。selectorは、どのコンポーネントが必要とし、どのstateに依存しているかを追跡するので、この機能的なアプローチがより効率的になります。

構成要素の観点から見ると、selectorとatomは同じ境界面を有するため、互いに置換することができます。

selectorは、selector関数を使用して定義します。

const fontSizeLabelState = selector({
  key: 'fontSizeLabelState',
  get: ({get}) => {
    const fontSize = get(fontSizeState);
    const unit = 'px';

    return `${fontSize}${unit}`;
  },
});

getプロパティは、計算される関数です。渡されたget引数を使用して、atomやその他のselectorの値にアクセスできます。別のatomまたはselectorにアクセスすると、依存関係が作成され、別のatomまたはselectorを更新すると、このatomまたはselectorが再計算されます。

このfontSizeLabelStateの例では、selectorにはfontSizeState atomという1つの依存関係があります。
概念的には、fontSizeLabelState selectorはfontSizeStateを入力として受け取り、フォーマットされたフォントサイズラベルを出力として返す純粋な関数のように動作します。

selectorは、useRecoilValue()を使用して読み取ることができます。
これは、atomまたはselectorを引数として取り、対応する値を返します。
fontSizeLabelState selectorが書き込み可能ではないため、useRecoilState()は使用しません。
(書き込み可能selectorの詳細については、selectorAPIリファレンスを参照してください。)

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  const fontSizeLabel = useRecoilValue(fontSizeLabelState);

  return (
    <>
      <div>Current font size: ${fontSizeLabel}</div>

      <button onClick={() => setFontSize(fontSize + 1)} style={{fontSize}}>
        Click to Enlarge
      </button>
    </>
  );
}

ボタンをクリックすると、ボタンのフォントサイズが大きくなり、現在のフォントサイズを反映するようにフォントサイズのラベルが更新されます。


参考サイト

公式ドキュメント
Pure function (純粋関数)とは
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳② コアコンセプト

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


コアコンセプト

概要

Recoilを使用すると、atom(共有state)からselector(純粋関数)を通ってReactコンポーネントに流れるデータフローグラフを作成できます。
atomは、コンポーネントが登録できるstateの単位です。selectorは、このstateを同期的または非同期的に変換します。

Atoms

atomはstateの単位です。
atomが更新されると、登録された各コンポーネントが新しい値で再描画されます。実行時にも作成できます。[React local component state] の代わりにatomを使用できます。同じatomが複数のコンポーネントから使用されている場合、それらのコンポーネントはすべてstateを共有します。

atomは、atom関数を使用して作成されます。

const fontSizeState = atom({
  key: 'fontSizeState',
  default: 14,
});

atomには一意のkeyが必要で、これはデバッグ、永続化、およびすべてのatomのマップを表示できる特定の高度なAPIに使用されます。
2つのatomが同じkeyを持つとエラーになるで、それらがグローバルに一意であることを確認してください。コンポーネントのstateと同様に、既定値もあります。

コンポーネントからatomを読み書きするには、useRecoilStateというHookを使用します。ReactのuseStateに似ているが、コンポーネント間でstateを共有できるようになります。

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return (
    <button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}>
      Click to Enlarge
    </button>
  );
}

ボタンをクリックすると、ボタンのフォントサイズが1つ大きくなります。
他のコンポーネントでも同じフォントサイズを使用できるようになりました。

function Text() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  return <p style={{fontSize}}>This text will increase in size too.</p>;
}

Selectors

selectorは、atomやその他のselectorを入力として受け付ける純粋な関数です。
これらの上流のatomまたはselectorが更新されると、selector関数が再評価されます。
コンポーネントはatomと同じようにselectorに登録でき、selectorが変更されると再レンダリングされます。

selectorは、stateに基づく派生データを計算するために使用されます。これにより冗長なstateを避けることができ、通常はreducerがstateを同期させて有効に保つ必要がなくなります。その代わりに、stateの最小セットはatomに格納され、それ以外はすべて、その最小stateの関数として効率的に計算されます。selectorは、どのコンポーネントが必要とし、どのstateに依存しているかを追跡するので、この機能的なアプローチがより効率的になります。

構成要素の観点から見ると、selectorとatomは同じ境界面を有するため、互いに置換することができます。

selectorは、selector関数を使用して定義します。

const fontSizeLabelState = selector({
  key: 'fontSizeLabelState',
  get: ({get}) => {
    const fontSize = get(fontSizeState);
    const unit = 'px';

    return `${fontSize}${unit}`;
  },
});

getプロパティは、計算される関数です。渡されたget引数を使用して、atomやその他のselectorの値にアクセスできます。別のatomまたはselectorにアクセスすると、依存関係が作成され、別のatomまたはselectorを更新すると、このatomまたはselectorが再計算されます。

このfontSizeLabelStateの例では、selectorにはfontSizeState atomという1つの依存関係があります。
概念的には、fontSizeLabelState selectorはfontSizeStateを入力として受け取り、フォーマットされたフォントサイズラベルを出力として返す純粋な関数のように動作します。

selectorは、useRecoilValue()を使用して読み取ることができます。
これは、atomまたはselectorを引数として取り、対応する値を返します。
fontSizeLabelState selectorが書き込み可能ではないため、useRecoilState()は使用しません。
(書き込み可能selectorの詳細については、selectorAPIリファレンスを参照してください。)

function FontButton() {
  const [fontSize, setFontSize] = useRecoilState(fontSizeState);
  const fontSizeLabel = useRecoilValue(fontSizeLabelState);

  return (
    <>
      <div>Current font size: ${fontSizeLabel}</div>

      <button onClick={() => setFontSize(fontSize + 1)} style={{fontSize}}>
        Click to Enlarge
      </button>
    </>
  );
}

ボタンをクリックすると、ボタンのフォントサイズが大きくなり、現在のフォントサイズを反映するようにフォントサイズのラベルが更新されます。


参考サイト

公式ドキュメント
Pure function (純粋関数)とは
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳①

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

  • 前書き
    • 動機
    • コアコンセプト
    • インストール
    • 入門
  • 基本チュートリアル
  • ガイド
  • APIリファレンス

動機

互換性と単純さの理由から、外部のグローバル状態ではなく、Reactに組み込まれている状態(state)管理機能を使用することをお勧めします。

しかし、Reactにはいくつかの制限があります。

  • コンポーネントの状態は、共通の祖先に押し上げることによってのみ共有できますが、これには再レンダリングが必要な巨大なツリーが含まれる場合があります。
  • コンテキストは単一の値のみを格納でき、それぞれが独自のコンシューマを持つ値の不確定なセットは格納できません。
  • どちらの方法でも、木(ツリー)の上部(stateが存在しなければならない場所)と葉(stateが使用される場所)をコード分割するのは困難です。

APIとセマンティクスと振る舞いの両方を可能な限りReactらしく維持しながら、これを改善したいと考えています。

Recoilは、Reactツリーに直交するだけでなく、固有かつ添付(アタッチ)された有向グラフを定義します。
state変化は、このグラフの根(我々はatomと呼んでいます)から純粋な関数(selectorと呼んでいます)を通ってコンポーネントへと流れます。
この方法では、次のようになります。

  • 共有しているstateが、React local state(必要に応じてReducer等でカプセル化することができる)と同じ単純なget/setインターフェースを持つ、定型のないAPIを入手しました。
  • Concurrent Modeやその他のReactの新機能が利用可能になれば、それらと互換性を持つ可能性があります。
  • state定義は増分及び分散されているため、コード分割が可能です。
  • stateは、それを使用するコンポーネントを変更することなく、派生データで置き換えることができます。
  • 派生データは、それを使用するコンポーネントを変更することなく、同期と非同期の間で移動できます。
  • ナビゲーションは、linkにおけるstate遷移の符号化(エンコーディング)さえも、第一級の概念として扱うことができる。
  • 後方互換性のある方法でアプリケーションのstate全体を永続化するのは簡単なので、永続化されたstateはアプリケーションの変更に耐えることができます。

参考サイト

公式ドキュメント
フリーソフトによるデータ解析・マイニング 第61回 ←(有向グラフ)
Pure function (純粋関数)とは
みらい翻訳


全目次

  • 前書き
    • 動機
    • コアコンセプト
    • インストール
    • 入門
  • 基本チュートリアル
    • イントロ
    • Atoms
    • Selectors
  • ガイド
    • 非同期データクエリ
    • 非同期状態(state)同期
    • 状態(state)の永続性
  • APIリファレンス
    • Core
    • 実用(utils)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Recoil公式ドキュメント 翻訳① 動機

Recoilの公式ドキュメントをgoogle翻訳するとコードまで翻訳されてしまうのが面倒なのでQiitaにまとめてみます。

追々追加していきます。(多分)

公式ドキュメント

目次

全目次は一番下にあります


動機

互換性と単純さの理由から、外部のグローバル状態ではなく、Reactに組み込まれている状態(state)管理機能を使用することをお勧めします。

しかし、Reactにはいくつかの制限があります。

  • コンポーネントの状態は、共通の祖先に押し上げることによってのみ共有できますが、これには再レンダリングが必要な巨大なツリーが含まれる場合があります。
  • コンテキストは単一の値のみを格納でき、それぞれが独自のコンシューマを持つ値の不確定なセットは格納できません。
  • どちらの方法でも、木(ツリー)の上部(stateが存在しなければならない場所)と葉(stateが使用される場所)をコード分割するのは困難です。

APIとセマンティクスと振る舞いの両方を可能な限りReactらしく維持しながら、これを改善したいと考えています。

Recoilは、Reactツリーに直交するだけでなく、固有かつ添付(アタッチ)された有向グラフを定義します。
state変化は、このグラフの根(我々はatomと呼んでいます)から純粋な関数(selectorと呼んでいます)を通ってコンポーネントへと流れます。
この方法では、次のようになります。

  • 共有しているstateが、React local state(必要に応じてReducer等でカプセル化することができる)と同じ単純なget/setインターフェースを持つ、定型のないAPIを入手しました。
  • Concurrent Modeやその他のReactの新機能が利用可能になれば、それらと互換性を持つ可能性があります。
  • state定義は増分及び分散されているため、コード分割が可能です。
  • stateは、それを使用するコンポーネントを変更することなく、派生データで置き換えることができます。
  • 派生データは、それを使用するコンポーネントを変更することなく、同期と非同期の間で移動できます。
  • ナビゲーションは、linkにおけるstate遷移の符号化(エンコーディング)さえも、第一級の概念として扱うことができる。
  • 後方互換性のある方法でアプリケーションのstate全体を永続化するのは簡単なので、永続化されたstateはアプリケーションの変更に耐えることができます。

参考サイト

公式ドキュメント
フリーソフトによるデータ解析・マイニング 第61回 ←(有向グラフ)
Pure function (純粋関数)とは
みらい翻訳


全目次

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む