[TS] 지금 안 들리는 리콜.

개시하다


이번에는 Recoil에 대한 소개(+자신의 학습 노트)입니다.RecoilFacebook를 대상으로 개발한React의 상태 관리 전체 프로그램 라이브러리입니다.
다음 글에서도 Zenn의 컨디션 관리가 활용돼 현재 시장 점유율을 확대하고 있는 라이브러리라고 할 수 있다.
https://zenn.dev/catnose99/articles/zenn-dev-stack Javascript의 실시례에서 자주 볼 수 있기 때문에 이번에 사용Typescript에 기재된 예를 소개합니다.

원래 리콜은...


실복 소개에 앞서 Recoil.RecoilFacebook가 2020년 5월에 발표한 상태 관리 라이브러리다.
다음은 공식 페이지입니다.
https://recoiljs.org
마찬가지로 상태 관리를 하는 프로그램 라이브러리Redux로서 남다른 인상을 주지만 실제로 사용하면 크게 다르다.
특히'데이터 스토어 취합 여부'는 사상에 큰 차이가 있어 그 성격이 사용에 직접 반영된다.
React Hooks와도 친화성이 좋고, useState 등과 같은 기법·용법을 하고 있기 때문에 이미Functional Component + Hooks 중심으로 개발됐다면 쉽게 이해할 수 있을 것 같다.
주의해야 할 것은 현재Experimental(실험성)의 창고에 있다.
향후 지원 등을 고려해 제품에 더 빨리 포함할 수도 있다.

샘플


이번에 실시된 응용 프로그램의 샘플은 다음과 같다.
recoil_sample
일반적인 TODO 응용 프로그램에서 작업을 추가, 읽어들일 수 있습니다.

버전 정보

  • [email protected]
  • [email protected]
  • [email protected]
  • 이루어지다


    다음 단계에 따라 설치합니다.

    프로젝트 작성


    다음 명령을 사용하여 프로젝트를 만듭니다.
    프로젝트 이름은 recoil-ts-sample입니다.
    npx create-react-app recoil-ts-sample --template typescript
    cd recoil-ts-sample
    

    Recoil 설치


    설치Recoil.
    yarn add recoil
    

    types 만들기


    우선 이 프로그램에서 '작업' 을 만듭니다. type소스는src/types/Todo.ts.
    이번에는 title만 있는 Todo형을 간단하게 정의했다.
    src/types/Todo.ts
    type Todo = {
        title : string;
    }
    export default Todo;
    

    Atom 만들기


    다음은 Atom 제작입니다.AtomRecoil 중의 데이터 저장소를 가리키며 atom()를 사용하여 선언한다.atom() 유형의 대상을 AtomOptions에 건네주다.AtomOptions는 다음과 같은 유형이다.
    // atom.d.ts
    export interface AtomOptions<T> {
      key: NodeKey;
      default: RecoilValue<T> | Promise<T> | T;
      effects_UNSTABLE?: ReadonlyArray<AtomEffect<T>>;
      dangerouslyAllowMutability?: boolean;
    }
    
    필요한 것은 keydefault뿐이다.key는 전체 응용 프로그램의 유일한 문자열이고 defaultAtom로 상태 관리가 필요한 값의 초기 값이다.
    예를 들어 응용 프로그램에 표시된 '작업 일람' Atom 에서 다음과 같이 선언했다.
    src/atoms/TodoListAtom.ts
    import { atom } from "recoil";
    import Todo from '../types/Todo';
    
    export const todoListState = atom<Todo[]>({
        // keyは"todoList"
        key: "todoList",
        // 初期値として3件のタスクを持つ配列を宣言
        default: [
            {title: "one"},
            {title: "two"},
            {title: "three"},
        ],
    });
    
    마찬가지로 Atom에서 화면 위에 있는'추가할 작업 이름의 필드'와'문자열을 검색하는 필드'의 상태를 설명합니다.
    src/atoms/TodoTitleFormAtom.ts
    import { atom } from "recoil";
    
    export const todoTitleFormState = atom<string>({
        key: "todoTitleForm",
        default: '',
    });
    
    src/atoms/SearchTextFormAtom.ts
    import { atom } from "recoil";
    
    export const searchTextFormState = atom<string>({
        key: "searchTextForm",
        default: '',
    });
    
    Atom의 선언이 Redux 중의 Store라고 이해한다면 좋겠다.

    셀렉터의 제작


    똑같이 만들기Selector.Selector 사용Atom의 값을 되돌려 어떤 계산, 가공, 부작용의 결과를 처리했다.
    이번 응용 프로그램의 예에서'실제 화면에 나타난 작업 일람'은 사용Selector으로 얻은 값이다.
    실제 화면에 표시되는 작업은 모든 작업에서 검색 필드에 입력한 문자만 표시됩니다.Selector의 성명은 selector()에서 진행되었다.ReadOnlySelectorOptions 유형의 대상을 매개 변수로 전송해야 합니다.ReadOnlySelectorOptions 모델은 다음과 같습니다.
    export interface ReadOnlySelectorOptions<T> {
        key: string;
        get: (opts: { get: GetRecoilValue }) => Promise<T> | RecoilValue<T> | T;
        dangerouslyAllowMutability?: boolean;
    }
    
    Atom도 유일성key을 가지고 있다.
    '어떤 값을 얻느냐'get를 정의하는 것도 있다.get는 매개 변수GetRecoilValue 유형get(속성 이름이 같기 때문에 번거롭다...)으로 속성 중의 대상을 받아들이는 함수입니다.
    실제 제작된Selector은 다음과 같다.
    src/selectors/SearchedTodoListSelector.ts
    import { selector } from "recoil";
    import { todoListState } from '../atoms/TodoListAtom';
    import { searchTextFormState } from '../atoms/SearchTextFormAtom';
    import Todo from '../types/Todo';
    
    export const searchedTodoListSelector = selector<Todo[]>({
      key: "searchedTodoListSelector",
      // getは{ get }を引数に取る関数
      get: ({ get }) => {
        // 引数のgetを使ってAtomから最新の値を取得(タスク一覧)
        const todoList: Todo[] = get(todoListState);
        // 同様に検索フィールドの文字列を取得
        const searchText: string = get(searchTextFormState);
        // 検索フィールドに入力がある場合は、その条件に合致したタスクのみを返却する
        return searchText? todoList.filter((t) => t.title.includes(searchText)) : todoList;
      },
    });
    

    Root의 선언


    이로써 Recoil 상태 관리에 대한 준비가 완료되었습니다.Recoil에서 상태 관리를 하기 위해서는 상태 관리를 하려는 곳<RecoilRoot>으로 싸야 한다.Redux에서 말한 <Provider>에 랩을 씌운 것과 같은 느낌이에요.index.tsx 내 사용RecoilRoot 가방App.
    index.tsx
    import React from "react";
    import ReactDOM from "react-dom";
    import { RecoilRoot } from "recoil";
    import App from "./App";
    
    ReactDOM.render(
      <React.StrictMode>
        <RecoilRoot>
          <App />
        </RecoilRoot>
      </React.StrictMode>,
      document.getElementById("root")
    );
    
    // ...以下略
    

    Atom 또는 Selector에서 값 가져오기


    그럼, 우리 빨리 구성 요소 AtomSelector 에서 수치를 얻읍시다.useRecoilValue()를 사용하여 값을 가져옵니다.useRecoilValue()에서 성명한 AtomSelector를 매개 변수로 전달한다.Atom 또는 Selector의 최신 값을 반환합니다.
    예를 들어, 작업 일람TodoList.tsx은 다음과 같습니다.
    src/component/TodoList.tsx
    import { useRecoilValue } from "recoil";
    import { searchedTodoListSelector } from "../selectors/SearchedTodoListSelector";
    import Todo from "../types/Todo";
    
    const TodoList: React.FC = () => {
      // useRecoilValueにsearchedTodoListSelectorを渡す
      // 返される値はsearchedTodoListSelectorのget()で定義した通りTodo[]
      const list: Todo[] = useRecoilValue(searchedTodoListSelector);
      return (
        <div>
          <p>タスク一覧</p>
          <ul>
            {list.map((todo: Todo, i: number) => {
              return <li key={`${todo.title}_${i}`}>{todo.title}</li>;
            })}
          </ul>
        </div>
      );
    };
    
    export default TodoList;
    

    Atom 값 변경

    Redux에서 Store의 값Action을 통해 Dispatch을 변경한 후 참조된 어셈블리에서 다시 그렸습니다.Recoil에서도 수정Atom의 값을 통해 참고Selector나 구성 요소에 자동으로 반영됩니다.Atom의 값을 변경하기 위해 useSetRecoilState()를 매개 변수로 Atom에 넘깁니다.
    반환 SetterOrUpdater<T> 형식의 함수를 반환 값으로 합니다.
    이것은 Atom값의 Setter 함수에 대해 이 함수 업데이트Atom를 통해 상술한 재계산 처리를 한다.
    예를 들어, 추가할 작업 이름의 필드 입력 구성 요소TitleForm.tsx는 다음과 같습니다.
    src/component/TitleForm.tsx
    import { useCallback } from "react";
    import { useRecoilValue, useSetRecoilState, SetterOrUpdater } from "recoil";
    import { todoTitleFormState } from "../atoms/TodoTitleFormAtom";
    
    const TitleForm: React.FC = () => {
      // useRecoilValueでtodoTitleFormStateの値を取得
      const todoTitleFormValue: string = useRecoilValue(todoTitleFormState);
      // useSetRecoilStateでtodoTitleFormStateの値を更新するSetter関数を取得
      const setTodoTitleFormValue: SetterOrUpdater<string> = useSetRecoilState(
        todoTitleFormState
      );
      // テキストフィールドのonChange処理
      const onChange = useCallback(
        (event: React.ChangeEvent<HTMLInputElement>) => {
          // 先に取得したsetTodoTitleFormValueに対して更新したい値を渡して実行
          setTodoTitleFormValue(event.target.value);
        },
        [setTodoTitleFormValue]
      );
    
      return (
        <label>
          タスク名:
          <input
            type="text"
            value={todoTitleFormValue}
            onChange={onChange}
            name="title"
            style={{ margin: 12 }}
          />
        </label>
      );
    };
    
    export default TitleForm;
    
    마찬가지로 검색 문자열 입력 필드 구성 요소를 만들 수도 있습니다.
    src/component/SearchForm.tsx
    import { useCallback } from "react";
    import { useRecoilValue, useSetRecoilState, SetterOrUpdater } from "recoil";
    import { searchTextFormState } from "../atoms/SearchTextFormAtom";
    
    const SearchForm: React.FC = () => {
      const searchTextFormValue: string = useRecoilValue(searchTextFormState);
      const setSearchTextFormValue: SetterOrUpdater<string> = useSetRecoilState(
        searchTextFormState
      );
      const onChange = useCallback(
        (event: React.ChangeEvent<HTMLInputElement>) => {
          setSearchTextFormValue(event.target.value);
        },
        [setSearchTextFormValue]
      );
    
      return (
        <label>
          検索:
          <input
            type="text"
            value={searchTextFormValue}
            onChange={onChange}
            name="title"
            style={{ margin: 12 }}
          />
        </label>
      );
    };
    
    export default SearchForm;
    
    또한'퀘스트의 추가'를 진행하는 단추 구성 요소도 준비해야 한다.
    src/component/AddButton.tsx
    import { useCallback } from "react";
    import { useRecoilValue, useSetRecoilState, SetterOrUpdater } from "recoil";
    import { todoTitleFormState } from "../atoms/TodoTitleFormAtom";
    import { todoListState } from "../atoms/TodoListAtom";
    import Todo from "../types/Todo";
    
    const AddButton: React.FC = () => {
      const todoList: Todo[] = useRecoilValue(todoListState);
      const todoTitleFormValue: string = useRecoilValue(todoTitleFormState);
      const setTodoList: SetterOrUpdater<Todo[]> = useSetRecoilState(todoListState);
      const setTitleFormValue: SetterOrUpdater<string> = useSetRecoilState(
        todoTitleFormState
      );
    
      const onClick = useCallback(() => {
        setTodoList([...todoList, { title: todoTitleFormValue }]);
        // タスクを追加したら入力欄は空にする
        setTitleFormValue("");
      }, [todoList, todoTitleFormValue, setTodoList, setTitleFormValue]);
    
      return <button onClick={onClick}>追加</button>;
    };
    
    export default AddButton;
    

    App 편집


    이로써 필요한 구성 요소의 제작이 완료되었다.App.tsx를 다음과 같은 내용으로 개작하여 실제 사용Recoil의 구성 요소 그룹을 사용합니다.
    App.tsx
    import "./App.css";
    import TitleForm from "./component/TitleForm";
    import AddButton from "./component/AddButton";
    import TodoList from "./component/TodoList";
    import SearchForm from "./component/SearchForm";
    
    const App: React.FC = () => {
      return (
        <div style={{ margin: 12 }}>
          <div>
            <TitleForm />
            <AddButton />
          </div>
          <SearchForm />
          <TodoList />
        </div>
      );
    };
    
    export default App;
    
    다음 명령으로 순조롭게 시작하면 처음에 소개한 샘플과 같은 프로그램이 시작됩니다.
    yarn start
    

    이번에 만든 거.


    상기 원본 파일은 GitHub의 다음 창고에 제출되었습니다.
    실행하는 동안 원본 파일을 추적하려면 을 참조하십시오.
    https://github.com/ShutoYamada/recoil-ts-sample

    총결산


    이번에 소개한 것은 Recoil 사용Typescript으로 간단한 임무 관리 앱을 제작하는 것에 관한 것이다.
    평상시 사용Redux 개발 중입니다.Recoil의 제작이 간단하고 직관적이기 때문에 이해하기 쉽다고 생각합니다.
    또한 Hooks처럼 편리하게 사용할 수 있는 소프트웨어도 현대React 응용 프로그램과 비슷해서 후발 라이브러리의 강점이라고 생각합니다.
    그래도Experimental 처리로 향후 사용감과 지원에 큰 변화가 있을 가능성이 있지만 개인적으로는 앞으로도 계속 발전할 유익한 프로그램 라이브러리로 꼽힌다.

    좋은 웹페이지 즐겨찾기