如何使用ReactHooks构建一个React待办事项应用程序

来自菜鸟教程
跳转至:导航、​搜索

介绍

React 是一个前端 JavaScript 库,可用于为您的应用程序创建交互式用户界面。

在本教程中,您将创建一个待办事项应用程序。 您的应用程序将需要显示任务、添加新任务、将任务标记为完成以及删除任务。 这些操作将涉及 CRUD(创建、读取、更新和删除) 应用程序的四个方面。

此类项目通常使用 Class 组件完成,但此应用程序将集成 React Hooks。 React Hooks 允许功能组件具有状态并使用生命周期方法,允许您避免使用 Class 组件并拥有更多模块化和可读性的代码。

您可以在 CodeSandbox 上查看 已完成的项目。

先决条件

要完成本教程,您需要:

  • Node.js 安装在本地,您可以按照【X57X】如何安装Node.js 并创建本地开发环境【X126X】进行。
  • 熟悉 React 会有所帮助,但不是必需的。 你可以看看我们的 How To Code in React.js 系列。

第 1 步——启动一个 React 应用程序

首先,您需要创建一个新应用程序。 在您的终端窗口中,导航到您希望新应用程序所在的位置,然后键入:

npx create-react-app react-to-do

注意: 在 React 16.8 之前,您必须安装 React 16.7 的 alpha 版本才能使用 React Hooks。 在撰写本文时,Create React App 将安装支持 Hooks 的最新稳定版 React (16.13.1)。


接下来,导航到新的项目目录:

cd react-to-do

然后,运行项目:

npm start

在浏览器中导航到 localhost:3000 以查看旋转的 React 徽标。

您的应用程序现已设置好,您可以继续构建应用程序的其余部分。

第 2 步 — 设计您的应用程序

样式不是本教程的重点,但它有助于显示待办事项。

在代码编辑器中打开 App.css

nano src/App.css

将此文件的内容替换为您将在整个应用程序中使用的三个类:

src/App.css

.app {
  background: #209cee;
  height: 100vh;
  padding: 30px;
}

.todo-list {
  background: #e8e8e8;
  border-radius: 4px;
  max-width: 400px;
  padding: 5px;
}

.todo {
  align-items: center;
  background: #fff;
  border-radius: 3px;
  box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.15);
  display: flex;
  font-size: 12px;
  justify-content: space-between;
  margin-bottom: 6px;
  padding: 3px 10px;
}

这将为 apptodo-listtodo 创建 CSS 类。 它利用 vh(视口高度)单位和 flexbox 属性(align-itemsjustify-content)。

造型完成。 现在,您可以实现 CRUD 的各个方面。

第三步——阅读待办事项

让我们从 CRUD 的 Read 部分开始。 您将需要列出事物的列表,以便您可以阅读和查看列表。

使用类的待办事项应用程序类似于以下内容:

class App extends Component {
  state = {
    todos: [
      { text: "Learn about React" },
      { text: "Meet friend for lunch" },
      { text: "Build really cool todo app" }
    ]
  }

  setTodos = todos => this.setState({ todos });

  render() {
    return <div></div>
  }
}

您将使用 React Hooks,因此状态看起来与使用类时略有不同。

打开App.js

nano src/App.js

修改此文件,将以下行代码添加到 App 组件:

src/App.js

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  const [todos, setTodos] = React.useState([
    { text: "Learn about React" },
    { text: "Meet friend for lunch" },
    { text: "Build really cool todo app" }
  ]);

  return (
    // ...
  );
}

export default App;

该组件是一个功能组件。 在过去的 React 版本中,函数式组件无法处理状态,但现在,通过使用 Hooks,它们可以了。

  • 第一个参数 todos 是您要命名的状态。
  • 第二个参数 setTodos 将用于设置状态。

useState 的钩子是 React 用来钩入组件状态或生命周期的钩子。 然后,您将创建一个对象数组,您将拥有您的状态的开始。

您需要创建一个组件,以后可以在主 App 组件的 return 中使用。 您将调用它 Todo,它将传入 todo 并显示待办事项的 text 部分(todo.text)。

重新访问 App.js 并在 App 组件之前添加新的 Todo 组件:

src/App.js

import React from 'react';
import logo from './logo.svg';
import './App.css';

function Todo({ todo }) {
  return (
    <div className="todo">
      {todo.text}
    </div>
  );
};

function App() {
  // ...
}

export default App;

让我们创建一个项目列表。

重新访问 App.js 并将 return 的内容替换为以下新代码行:

src/App.js

function App() {
  // ...

  return (
    <div className="app">
      <div className="todo-list">
        {todos.map((todo, index) => (
          <Todo
            key={index}
            index={index}
            todo={todo}
          />
        ))}
      </div>
    </div>
  );
}

通过使用 JavaScript 方法 map(),您将能够通过从状态映射 todo 项目并按索引显示它们来创建新的项目数组。

这为 app 添加了 <div>,为 todo-list 添加了 <div>,以及 todosTodo 的映射组件。

此时,也可以将 logo.svg 移除,因为它将不再使用。

到目前为止,整个 src/App.js 文件将类似于以下内容:

src/App.js

import React from "react";
import "./App.css";

function Todo({ todo }) {
  return (
    <div className="todo">
      {todo.text}
    </div>
  );
};

function App() {
  const [todos, setTodos] = React.useState([
    { text: "Learn about React" },
    { text: "Meet friend for lunch" },
    { text: "Build really cool todo app" }
  ]);

  return (
    <div className="app">
      <div className="todo-list">
        {todos.map((todo, index) => (
          <Todo
            key={index}
            index={index}
            todo={todo}
          />
        ))}
      </div>
    </div>
  );
}

export default App;

在 Web 浏览器中打开您的应用程序。 将显示三个待办事项:

您现在正在读取数据并且可以继续处理 CRUD 的其他方面。

第 4 步 - 创建待办事项

现在,让我们让您的应用程序能够为您的待办事项应用程序创建一个新项目。

App.js 文件中,您需要添加一些内容。

首先,您将添加另一个名为 TodoForm 的组件。 在此组件中,您希望:

  • 从输入字段的空状态开始。
  • 能够通过设置状态来更新表单。
  • 处理提交。

要设置你的状态,你会这样写:

const [value, setValue] = React.useState("");

第一个是“价值”,第二个是你将如何设置状态。 状态一开始是空的,当您向状态添加内容时,它会将其添加到您的待办事项列表中。

您将需要添加一个 handleSubmit 变量来处理您的 addTodo 函数并将项目添加到列表中。 如果输入框中没有任何内容并且用户按下 ENTER,则您希望它不要将空项目添加到列表中。

将功能添加到具有输入框的表单中:

src/App.js

// ...

function TodoForm({ addTodo }) {
  const [value, setValue] = React.useState("");

  const handleSubmit = e => {
    e.preventDefault();
    if (!value) return;
    addTodo(value);
    setValue("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        className="input"
        value={value}
        onChange={e => setValue(e.target.value)}
      />
    </form>
  );
}

function App() {
  // ...
}

// ...

将这个新的 TodoForm 组件添加到您的 App 组件中:

src/App.js

function App() {
  // ...

  return (
    <div className="app">
      <div className="todo-list">
        {todos.map((todo, index) => (
          <Todo
            key={index}
            index={index}
            todo={todo}
          />
        ))}
        <TodoForm addTodo={addTodo} />
      </div>
    </div>
  );
}

现在让我们构建 addTodo 函数。

停留在 App.js 内,在 App 组件的状态下,该函数将能够抓取现有的项目列表,添加新项目并显示该新列表。

src/App.js

function App() {
  // ...

  const addTodo = text => {
    const newTodos = [...todos, { text }];
    setTodos(newTodos);
  };

  return(
    // ...
  );
}

请注意,没有 this.state。 使用新的 React Hooks,你将不再使用 this.state,因为新的 Hooks 知道它会在某些地方被暗示。

代码中还有一个 扩展运算符todos 之前的三个点会为您复制列表,以便您可以添加新的待办事项。 然后使用您之前设置的关键字,您将使用 setTodos 设置状态。

在 Web 浏览器中打开您的应用程序。 应该显示三个待办事项。 还应该有一个用于添加新待办事项的字段:

您现在正在创建数据并且可以继续处理 CRUD 的其他方面。

第 5 步 — 更新待办事项

让我们添加功能以在完成后划掉待办事项列表中的项目。

App 组件中的状态需要一些额外的“已完成”状态才能更改。 您将在对象列表中添加另一个键值对。

通过添加 isCompleted: false 值,您将首先将其设置为 false,并在出现提示时将其更改为 true

重新访问 App.js 并将 isCompleted 添加到您的状态:

src/App.js

function App() {
  const [todos, setTodos] = React.useState([
    {
      text: "Learn about React",
      isCompleted: false
    },
    {
      text: "Meet friend for lunch",
      isCompleted: false
    },
    {
      text: "Build really cool todo app",
      isCompleted: false
    }
  ]);

  // ...
}

您将需要一个类似 addTodo 函数的函数,但是这个函数将能够将一个项目标记为“完成”。 您将执行与 addTodo 中类似的操作,例如使用扩展运算符获取当前项目列表。 在此函数中,您将 isCompleted 状态更改为 true 以便它知道它已完成。 然后它将更新状态并将状态设置为 newTodos

使用以下内容更新您的代码:

src/App.js

function App() {
  // ...

  const completeTodo = index => {
    const newTodos = [...todos];
    newTodos[index].isCompleted = true;
    setTodos(newTodos);
  };

  return (
    // ...
  )
}

通过在 Todo 函数中使用 completeTodo,您可以使用该功能。 单击 Complete 按钮时,将添加 textDecoration: line-through 样式并划掉项目。

您将使用 三元运算符 来完成一个项目并更新列表:

src/App.js

function Todo({ todo, index, completeTodo }) {
  return (
    <div
      className="todo"
      style={{ textDecoration: todo.isCompleted ? "line-through" : "" }}
    >
      {todo.text}
      <div>
        <button onClick={() => completeTodo(index)}>Complete</button>
      </div>
    </div>
  );
}

在返回 App 组件的 Todo 部分添加 completeTodo

src/App.js

function App() {
  // ...

  return (
    <div className="app">
      <div className="todo-list">
        {todos.map((todo, index) => (
          <Todo
            key={index}
            index={index}
            todo={todo}
            completeTodo={completeTodo}
          />
        ))}
        <TodoForm addTodo={addTodo} />
      </div>
    </div>
  );
}

在 Web 浏览器中打开您的应用程序。 将显示三个待办事项。 还有一个 Complete 按钮,用于将待办事项标记为完成。

您现在正在更新数据,可以继续进行 CRUD 的最后一个方面。

第 6 步 — 删除待办事项

让我们添加功能以在待办事项列表中的项目被删除时删除它们。

您将构建 removeTodo 函数,以便当您单击 X 删除项目时,该项目将被删除。 该函数将被其他函数定位在 App 组件的状态下;

src/App.js

function App() {
  // ...

  const removeTodo = index => {
    const newTodos = [...todos];
    newTodos.splice(index, 1);
    setTodos(newTodos);
  };

  return (
    // ...
  )
}

在这个 removeTodo 函数中,您将再次使用扩展运算符,但是一旦您获取了当前列表,您将 拼接 从项目数组中选择的索引。 删除后,您将通过将 setTodos 设置为 newTodos 来返回新状态。

在您的 Todo 函数中,您需要添加一个按钮来删除待办事项:

src/App.js

function Todo({ todo, index, completeTodo, removeTodo }) {
  return (
    <div
      className="todo"
      style={{ textDecoration: todo.isCompleted ? "line-through" : "" }}
    >
      {todo.text}
      <div>
        <button onClick={() => completeTodo(index)}>Complete</button>
        <button onClick={() => removeTodo(index)}>x</button>
      </div>
    </div>
  );
}

在返回 App 组件的 Todo 部分添加 removeTodo

src/App.js

function App() {
  // ...

  return (
    <div className="app">
      <div className="todo-list">
        {todos.map((todo, index) => (
          <Todo
            key={index}
            index={index}
            todo={todo}
            completeTodo={completeTodo}
            removeTodo={removeTodo}
          />
        ))}
        <TodoForm addTodo={addTodo} />
      </div>
    </div>
  );
}

在 Web 浏览器中打开您的应用程序。 将显示三个待办事项。 还将有一个 X 按钮用于删除待办事项。

您现在正在删除数据并且已经实现了 CRUD 的所有四个方面。

第 7 步 — 完成应用程序

Todo 组件、TodoForm 组件和 App 组件放在一起后,您的 App.js 文件将如下所示:

src/App.js

import React from "react";
import "./App.css";

function Todo({ todo, index, completeTodo, removeTodo }) {
  return (
    <div
      className="todo"
      style={{ textDecoration: todo.isCompleted ? "line-through" : "" }}
    >
      {todo.text}
      <div>
        <button onClick={() => completeTodo(index)}>Complete</button>
        <button onClick={() => removeTodo(index)}>x</button>
      </div>
    </div>
  );
}

function TodoForm({ addTodo }) {
  const [value, setValue] = React.useState("");

  const handleSubmit = e => {
    e.preventDefault();
    if (!value) return;
    addTodo(value);
    setValue("");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        className="input"
        value={value}
        onChange={e => setValue(e.target.value)}
      />
    </form>
  );
}

function App() {
  const [todos, setTodos] = React.useState([
    {
      text: "Learn about React",
      isCompleted: false
    },
    {
      text: "Meet friend for lunch",
      isCompleted: false
    },
    {
      text: "Build really cool todo app",
      isCompleted: false
    }
  ]);

  const addTodo = text => {
    const newTodos = [...todos, { text }];
    setTodos(newTodos);
  };

  const completeTodo = index => {
    const newTodos = [...todos];
    newTodos[index].isCompleted = true;
    setTodos(newTodos);
  };

  const removeTodo = index => {
    const newTodos = [...todos];
    newTodos.splice(index, 1);
    setTodos(newTodos);
  };

  return (
    <div className="app">
      <div className="todo-list">
        {todos.map((todo, index) => (
          <Todo
            key={index}
            index={index}
            todo={todo}
            completeTodo={completeTodo}
            removeTodo={removeTodo}
          />
        ))}
        <TodoForm addTodo={addTodo} />
      </div>
    </div>
  );
}

export default App;

您现在拥有一个适用于 CRUD 的所有四个方面的应用程序。 创建待办事项、读取待办事项、更新待办事项、删除待办事项。

结论

当涉及到 Web 开发中的 CRUD 时,待办事项应用程序可以是一个很好的提醒或起点。 能够读取信息、创建新信息、更新现有信息和删除信息在任何应用程序中都非常强大。

在本教程中,您使用 React Hooks 创建了一个 CRUD 待办事项列表应用程序,它允许代码清晰、简洁和直接。

如果您想了解有关 React 的更多信息,请查看 我们的 React 主题页面 以获取练习和编程项目。