Introduceți React v16.7.0-alfa Cârlige, și sunt încântat.

Ce sunt cârligele?

Sunt funcții care vă oferă funcții React, cum ar fi cârlige de stare și ciclul de viață fără clase ES6.

Unele beneficii sunt

  • Izolarea logicii de stare, facilitând testarea.
  • Partajarea logicii de stare fără elemente de redare sau componente de ordin superior.
  • Separarea preocupărilor aplicației pe baza logicii, nu a cârligelor ciclului de viață.
  • Evitarea claselor ES6, pentru că sunt ciudate, nu chiar cursuri, și crește chiar și dezvoltatori JavaScript cu experiență.

Pentru mai multe detalii vezi Introducerea oficială a lui React, Hooks.

Adoptați cârligele treptat

La momentul scrierii, Hooks erau în alfa, iar API-ul lor s-ar fi putut schimba oricând.

React 16.8.0 a fost prima versiune stabilă care acceptă Hooks și există mai multe tutoriale și exemple de cod în fiecare zi. Cu toate acestea, deoarece nu există planuri de eliminare a claselor din React, iar Hooks va funcționa cu codul existent, echipa React recomandă evitarea „riscurilor mari”. În schimb, ei sugerează practicarea Hooks-urilor în componente non-critice mai întâi, apoi folosirea lor în locul cursurilor de mai departe.

Să construim o listă Todo

Cum se construieste o lista de lucruri cu React Hooks

Listele Todo sunt exemplul cel mai mult folosit dintr-un motiv bun – sunt practici fantastice. Vă recomand acest lucru pentru orice limbă sau bibliotecă pe care doriți să o încercați.

Al nostru va face doar câteva lucruri

  • Afișați-le pe toate într-un mod frumos de design material
  • Permiteți adăugarea tuturor prin intrare
  • Ștergeți toate

Înființat

Aici sunt GitHub și CodeSandbox link-uri.

git clone https://github.com/yazeedb/react-hooks-todo
cd react-hooks-todo
npm install

master sucursala are proiectul finalizat, așa că verificați start filiala dacă doriți să continuați.

git checkout start

Și rulați proiectul.

npm start

Aplicația ar trebui să ruleze localhost:3000și iată UI-ul nostru inițial.

Cum se construieste o lista de lucruri cu React Hooks

Este deja configurat cu material-ui pentru a oferi paginii noastre un aspect profesional. Să începem să adăugăm câteva funcționalități!

Componenta TodoForm

Adăugați un fișier nou, src/TodoForm.js. Iată codul de pornire.

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;

Având în vedere numele, știm că sarcina sa este de a adăuga todos la starea noastră. Apropo de asta, iată primul nostru cârlig.

useState

Verificați acest cod

import { useState } from 'react';

const [value, setValue] = useState('');

useState este doar o funcție care ia starea inițială și returnează o matrice. Mergeți înainte și console.log aceasta.

Primul index al matricei este valoarea curentă a stării dvs., iar al doilea index este o funcție de actualizare.

Așa că le-am numit în mod corespunzător value și setValue folosind Alocarea destructurării ES6.

useState cu formulare

Formularul nostru ar trebui să urmărească valoarea intrării și apelul saveTodo la supunere. useState ne poate ajuta cu asta!

Actualizați TodoForm.js, noul cod este în îndrăzneţ.

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>
  );
};

export default TodoForm;

Înapoi în index.js, importați și utilizați această componentă.

// ...

import TodoForm from './TodoForm';

// ...

const App = () => {
  return (
    <div className="App">
      <Typography component="h1" variant="h2">
        Todos
      </Typography>

      <TodoForm saveTodo={console.warn} />
    </div>
  );
};

Acum valoarea dvs. este conectată la trimitere (apăsați enter).

1611070026 391 Cum se construieste o lista de lucruri cu React Hooks

useState With Todos

De asemenea, avem nevoie de stat pentru toți. Import useState în index.js. Starea noastră inițială ar trebui să fie o matrice goală.

import React, { useState } from 'react';

// ...

const App = () => {
  const [todos, setTodos] = useState([]);

  // ...
};

Componenta TodoList

Creați un fișier nou numit src/TodoList.js.

Edit: Mulțumesc Takahiro Hata pentru că m-a ajutat să mă mișc onClick la locul corect!

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;

Este nevoie de două recuzită

  • todos: Matricea tuturor. Noi map peste fiecare și creați un element de listă.
  • deleteTodo: Dând clic pe un lucru IconButton declanșează această funcție. Trece de index, care va identifica în mod unic un lucru în lista noastră.

Importați această componentă în index.js.

import TodoList from './TodoList';
import './styles.css';

const App = () => {
  //...
};

Și folosește-l în App funcționează așa

<TodoForm saveTodo={console.warn} />
<TodoList todos={todos} />

Adăugarea Todos

Inca inauntru index.js, să edităm TodoFormrecuzita, saveTodo.

<TodoForm
  saveTodo={(todoText) => {
    const trimmedText = todoText.trim();

    if (trimmedText.length > 0) {
      setTodos([...todos, trimmedText]);
    }
  }}
/>

Pur și simplu combinați toate existentele cu noul nostru, spațiu alb suplimentar decupat.

Putem adăuga todos acum!

1611070026 570 Cum se construieste o lista de lucruri cu React Hooks

Ștergerea intrării

Observați că intrarea nu se șterge după adăugarea unui nou lucru. Este o experiență proastă pentru utilizator!

Îl putem remedia cu o mică modificare a codului TodoForm.js.

<form
  onSubmit={(event) => {
    event.preventDefault();

    saveTodo(value);

    setValue('');
  }}
/>

Odată salvat un lucru, setați starea formularului la un șir gol.

Acum arată bine!

1611070027 255 Cum se construieste o lista de lucruri cu React Hooks

Ștergerea tuturor

TodoList oferă fiecare lucru index, deoarece este un mod garantat de a-l găsi pe cel pe care dorim să-l ștergem.

TodoList.js

<IconButton
  aria-label="Delete"
  onClick={() => {
    deleteTodo(index);
  }}
>
  <DeleteIcon />
</IconButton>

Vom profita de asta în index.js.

<TodoList
  todos={todos}
  deleteTodo={(todoIndex) => {
    const newTodos = todos.filter((_, index) => index !== todoIndex);

    setTodos(newTodos);
  }}
/>

Orice toate nu se potrivesc cu cele furnizate index sunt păstrate și stocate în stare folosind setTodos.

Funcționalitatea de ștergere este completă!

1611070027 291 Cum se construieste o lista de lucruri cu React Hooks

Abstracționarea tuturor useState

Am menționat că Hooks sunt excelente pentru separarea stării și a logicii componentelor. Iată cum ar putea arăta asta în aplicația noastră pentru tot.

Creați un fișier nou numit 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);
    }
  };
};

Este același cod al nostru de la index.js, dar separat! Conducerea noastră de stat nu mai este strâns legată de componentă.

Acum, doar importați-l.

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);

Și totul funcționează în continuare ca normal.

1611070027 291 Cum se construieste o lista de lucruri cu React Hooks

Abstracție de introducere a formularului useState

La fel putem face și cu formularul nostru!

Creați un fișier nou, 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('')
  };
};

Si acum TodoForm.js ar trebui să arate așa.

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;

Și am terminat cu toții! Sper că ți-a plăcut, până data viitoare!