反応フックでtodoリストを構築する方法


この記事はもともと投稿されたEducative . これはYazeed Bzadough , 誰が啓発し、深い理解を教えることを期待し、開発者のための動機と教育コンテンツを作成します.彼は主にWebテクノロジに焦点を当てています.

フックは何ですか。


彼らは、あなたがES 6クラスなしで州とライフサイクルフックのような特徴を反応させる機能です.
いくつかの利点があります.
  • それは簡単にテストすることstatestロジカルロジックを分離します.
  • ステートフル論理を共有する小道具や高次のコンポーネントをレンダリングします.
  • ロジックに基づいてアプリケーションの懸念を分離、ライフサイクルのフック.
  • ES 6クラスを避けるのは、彼らが奇妙な、実際のクラスではないので、経験豊富なJavaScript開発者も旅行.
  • 詳細はReact’s official Hooks intro .
    生産に使用しないでください!このとき、フックはアルファである.APIはいつでも変更できます.私はあなたに実験をして、楽しんで、あなたの側プロジェクトでフックを使うことを勧めます、しかし、彼らが安定しているまで、生産コードではありません.

    Todoリストを作りましょう



    TODOリストは、良い理由のために最も使用される例です — 彼らは素晴らしい練習です.私はこれを試してみたい任意の言語やライブラリをお勧めします.
    私たちのものはほんの少ししかありません.
  • 素敵な素材デザインのファッション
  • 入力を介してtodosを追加する
  • 削除する
  • セットアップ


    ここに、GithubとCodesandBoxリンクがあります.
    git clone https://github.com/yazeedb/react-hooks-todo
    cd react-hooks-todo
    npm install
    
    The master ブランチは完成したプロジェクトを持っているので、チェックアウトstart あなたが沿って続くことを望むならば、分岐してください.git checkout startプロジェクトを実行します.npm startアプリを実行する必要がありますlocalhost:3000 , そしてここに私たちの最初のUIです.

    既に設定済みですmaterial-ui 我々のページに専門の観察を与えるために.若干の機能性を加え始めましょう!

    ToDoFormコンポーネント


    新しいファイルを追加します.src/TodoForm.js . これがスタートコードです.
    import React from 'react';
    import TextField from '@material-ui/core/TextField';
    
    const TodoForm = ({ saveTodo }) => {
      return (
        <form>
          <TextField variant="outlined" placeholder="Add todo" margin="normal" />
        </form>
      );
    };
    
    export default TodoForm;
    
    名前を考えれば、我々の仕事は我々の国家にtodosを加えることであるということを知っています.ここでは、我々の最初のフックです.

    米国不動産


    このコードをチェックアウトします.
    import { useState } from 'react';
    
    const [value, setValue] = useState('');
    
    useState は初期状態を取り、配列を返す関数です.どうぞconsole.log それ.
    配列の最初のインデックスはあなたの状態の現在の値です、そして、2番目のインデックスはupdater関数です.
    それで、私たちはそれらを適切に命名しましたvalue and setValue 使用ES6 destructuring assignment .

    米国不動産


    フォームは入力の値と呼び出しを追跡しますsaveTodo 提出する.useState 私たちを助けることができる!
    更新TodoForm.js , 新しいコードは太字です.
    import React, { useState } from 'react';
    import TextField from '@material-ui/core/TextField';
    
    const TodoForm = ({ saveTodo }) => {
      const [value, setValue] = useState('');
    
      return (
        <form
          onSubmit={(event) => {
            event.preventDefault();
            saveTodo(value);
          }}
        >
          <TextField
            variant="outlined"
            placeholder="Add todo"
            margin="normal"
            onChange={(event) => {
              setValue(event.target.value);
            }}
            value={value}
          />
        </form>
      );
    };
    
    バック・インindex.js , このコンポーネントをインポートして使用します.
    // ...
    
    import TodoForm from './TodoForm';
    
    // ...
    
    const App = () => {
      return (
        <div className="App">
          <Typography component="h1" variant="h2">
            Todos
          </Typography>
    
          <TodoForm saveTodo={console.warn} />
        </div>
      );
    };
    
    今すぐあなたの値のログを提出(Enterキーを押します).

    USDASによるUSENT


    また、我々のtodosのために州が必要です.輸入useState インindex.js . 初期状態は空の配列でなければなりません.
    import React, { useState } from 'react';
    
    // ...
    
    const App = () => {
      const [todos, setTodos] = useState([]);
    
      // ...
    };
    

    トドルストコンポーネント


    新しいファイルを作成するsrc/TodoList.js . ありがとうございますTakahiro Hata 私は正しい場所にonclick移動ヘルプ!
    import React from 'react';
    import List from '@material-ui/core/List';
    import ListItem from '@material-ui/core/ListItem';
    import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
    import ListItemText from '@material-ui/core/ListItemText';
    import Checkbox from '@material-ui/core/Checkbox';
    import IconButton from '@material-ui/core/IconButton';
    import DeleteIcon from '@material-ui/icons/Delete';
    
    const TodoList = ({ todos, deleteTodo }) => (
      <List>
        {todos.map((todo, index) => (
          <ListItem key={index.toString()} dense button>
            <Checkbox tabIndex={-1} disableRipple />
            <ListItemText primary={todo} />
            <ListItemSecondaryAction>
              <IconButton
                aria-label="Delete"
                onClick={() => {
                  deleteTodo(index);
                }}
              >
                <DeleteIcon />
              </IconButton>
            </ListItemSecondaryAction>
          </ListItem>
        ))}
      </List>
    );
    
    export default TodoList;
    
    それは2つの小道具
  • Todos : todosの配列.我々map それぞれの上に、リストの項目を作成します.
  • DeleteTodo : TODOのクリックIconButton この関数を起動します.それはindex , リストのtodoを一意に識別する.
  • このコンポーネントをインポートしますindex.js .
    import TodoList from './TodoList';
    import './styles.css';
    
    const App = () => {
      //...
    };
    
    そして、あなたのApp 関数:
    <TodoForm saveTodo={console.warn} />
    <TodoList todos={todos} />
    

    追加


    依然index.js , 編集しましょうTodoForm ’s propsaveTodo .
    <TodoForm
      saveTodo={(todoText) => {
        const trimmedText = todoText.trim();
    
        if (trimmedText.length > 0) {
          setTodos([...todos, trimmedText]);
        }
      }}
    />
    
    単に私たちの新しいもの、余分な空白のカットと既存のtodosをマージします.
    今すぐ追加することができます!

    入力のクリア


    新しいtodoを追加した後、入力がクリアされていないことに注意してください.それは悪いユーザー体験です!
    私たちは小さなコードの変更で修正することができますTodoForm.js .
    <form
      onSubmit={(event) => {
        event.preventDefault();
    
        saveTodo(value);
    
        setValue('');
      }}
    />
    
    todoを保存すると、フォームの状態を空の文字列に設定します.
    それは今、良い探しです!

    削除する

    TodoList 各藤堂のindex , それは削除する1つを見つけるために保証された方法です.TodoList.js
    <IconButton
      aria-label="Delete"
      onClick={() => {
        deleteTodo(index);
      }}
    >
      <DeleteIcon />
    </IconButton>
    
    我々はそれを利用するindex.js .
    <TodoList
      todos={todos}
      deleteTodo={(todoIndex) => {
        const newTodos = todos.filter((_, index) => index !== todoIndex);
    
        setTodos(newTodos);
      }}
    />
    
    どのようなtodosが一致していないindex を保存し、setTodos .
    削除機能は完了です!

    米国の不動産を抽象化すること


    私はフックは状態とコンポーネントのロジックを分離するために大きいと述べた.ここでは、我々のtodoアプリのように見えるかもしれないです.
    新しいファイルを作成するsrc/useTodoState.js .
    import { useState } from 'react';
    
    export default (initialValue) => {
      const [todos, setTodos] = useState(initialValue);
    
      return {
        todos,
        addTodo: (todoText) => {
          setTodos([...todos, todoText]);
        },
        deleteTodo: (todoIndex) => {
          const newTodos = todos.filter((_, index) => index !== todoIndex);
    
          setTodos(newTodos);
        }
      };
    };
    
    それは私たちの同じコードですindex.js , しかし、分離!私たちの国家管理は、もはやしっかりとコンポーネントに結合されていません.
    今すぐそれをインポートします.
    import React from 'react';
    import ReactDOM from 'react-dom';
    import Typography from '@material-ui/core/Typography';
    import TodoForm from './TodoForm';
    import TodoList from './TodoList';
    import useTodoState from './useTodoState';
    import './styles.css';
    
    const App = () => {
      const { todos, addTodo, deleteTodo } = useTodoState([]);
    
      return (
        <div className="App">
          <Typography component="h1" variant="h2">
            Todos
          </Typography>
    
          <TodoForm
            saveTodo={(todoText) => {
              const trimmedText = todoText.trim();
    
              if (trimmedText.length > 0) {
                addTodo(trimmedText);
              }
            }}
          />
    
          <TodoList todos={todos} deleteTodo={deleteTodo} />
        </div>
      );
    };
    
    const rootElement = document.getElementById('root');
    ReactDOM.render(<App />, rootElement);
    
    そして、すべてはまだ正常に動作します.

    フォーム入力


    我々は、我々の形で同じことをすることができます!
    新しいファイルを作成します.src/useInputState.js .
    import { useState } from 'react';
    
    export default (initialValue) => {
      const [value, setValue] = useState(initialValue);
    
      return {
        value,
        onChange: (event) => {
          setValue(event.target.value);
        },
        reset: () => setValue('')
      };
    };
    
    そして今TodoForm.js 以下のようになります.
    import React from 'react';
    import TextField from '@material-ui/core/TextField';
    import useInputState from './useInputState';
    
    const TodoForm = ({ saveTodo }) => {
      const { value, reset, onChange } = useInputState('');
    
      return (
        <form
          onSubmit={(event) => {
            event.preventDefault();
    
            saveTodo(value);
            reset();
          }}
        >
          <TextField
            variant="outlined"
            placeholder="Add todo"
            margin="normal"
            onChange={onChange}
            value={value}
          />
        </form>
      );
    };
    
    export default TodoForm;
    
    そして、我々はすべて完了です!あなたが楽しんで希望、次まで!
    あなたがフックで働くことに関する詳細な情報を望むならば、あなたは訪問することができますAdvanced React Patterns with Hooks . また、あなたがYazeedの仕事の詳細を見たい場合は、彼のコースをチェックアウトすることができますFunctional Programming Patterns with RamdaJS .