react-hooks_如何使用React Hooks构建React To-Do应用

react-hooks

介绍 (Introduction)

React is a front-end JavaScript library that can be used to create interactive user interfaces for your application. In this tutorial, you will create a to-do app that covers all four aspects of a CRUD: Create, Read, Update, and Delete.

React是一个前端JavaScript库,可用于为您的应用程序创建交互式用户界面。 在本教程中,您将创建一个待办事项应用程序,其中涵盖了CRUD的所有四个方面:创建,读取,更新和删除。

This type of project is often done with Class components, but this application will instead integrate React Hooks. React Hooks allow for functional components to have a state and utilize lifecycle methods, allowing you to avoid using class components and have more modular and readable code.

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

You can check out the completed project at the CodeSandbox for this project.

您可以在CodeSandbox上签出完成的项目

第1步—启动React应用 (Step 1 — Starting a React App)

Navigate to the place you would like your new application to be located and type:

导航到您希望新应用程序位于的位置,然后键入:

  • npx create-react-app react-to-do

    npx create-react-app react-to-do

Note: Running npx before the command allows it to be installed if it is not already installed globally on your machine.

注意:如果尚未在计算机上全局安装npx ,请在命令之前运行npx

Once it is done, navigate into the project:

完成后,导航到项目:

  • cd react-to-do

    光盘React

Then run the project:

然后运行项目:

  • npm run start

    npm运行开始

Navigate to http://localhost:3000/ in your browser to see the spinning React logo.

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

At the time of this writing, React Hooks are in React 16.7, but React 16.7 is in alpha. You’ll need to install that specifically until it comes out of alpha:

在撰写本文时,React Hooks在React 16.7中,但是React 16.7在alpha中。 您需要专门安装它,直到它脱离alpha:

  • npm install -S react@16.7.0-alpha.2 react-dom@16.7.0-alpha.2

    npm install -S react@16.7.0-alpha.2 react-dom@16.7.0-alpha.2

步骤2 —样式化您的应用程序 (Step 2 — Styling Your Application)

Move into your src/App.css file and add in the three classes we will be using throughout our app. Styling won’t be the focus of this tutorial, so we’ll keep this section short.

移至src/App.css文件,并添加我们将在整个应用程序中使用的三个类。 样式将不是本教程的重点,因此我们将使本节简短。

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

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

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

步骤3 —阅读项目列表 (Step 3 — Reading a List of Items)

With your application running and the styling ready to be used, let’s start on the Read part of CRUD. We’ll want to make a list of things so that we can Read/view the list.

运行您的应用程序并准备使用样式后,让我们从CRUD的“读取”部分开始。 我们将列出所有内容,以便我们可以阅读/查看列表。

增加状态 (Adding in State)

Go into your src/App.js file and add a state to our component. We are going to be using React Hooks, so state will look a little different than if we used classes.

进入您的src/App.js文件,并向我们的组件添加状态。 我们将使用React Hooks,因此状态看起来与我们使用类的情况有所不同。

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

  // we'll render our todos here ...
  // return <div></div>
}

The component is a functional component. In past versions of React, functional components were unable to handle state, but now, by using Hooks, they can.

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

  • The first parameter, todos, is what we are going to name our state.

    第一个参数todos是我们要命名状态的名称。

  • The second parameter, setTodos, is what we are going to use to set the state.

    第二个参数setTodos是我们用来设置状态的参数。

The hook of useState is what React uses to hook into the state or lifecycle of the component. We then create an array of objects and we have the beginnings of our state.

useState的挂钩是React用于挂钩到组件的状态或生命周期的东西。 然后,我们创建一个对象数组,并且我们有了状态的起点。

与类组件比较 (Comparing to a Class Component)

Let’s take a moment to see how this would’ve been done with classes:

让我们花点时间看一下如何对类进行处理:

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 allows for much cleaner code.

React Hooks允许使用更简洁的代码。

我们的Todo组件 (Our Todo Component)

We will want to create a component that we can use later on in the return of the main App component. We will call that Todo and it will pass in the todo and show the “text” part of the todo (todo.text), like so:

我们将要创建一个组件,稍后在返回主App组件时可以使用。 我们将其称为Todo ,它将传递todo并显示todo的“文本”部分( todo.text ),如下所示:

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

Let’s see how we will use that in our App component.

让我们看看如何在App组件中使用它。

使用Todo变量获取返回的列表 (Using the Todo Variable to Get a List Returned)

Go down to the return part of the App component and remove almost everything. We want to empty out that return part so that the spinning logo we saw earlier when we navigated to http://localhost:3000 goes away. Instead, our list will be displayed on the page.

转到App组件的return部分,并删除几乎所有内容。 我们想清空返回部分,以便我们之前导航到http://localhost:3000时看到的旋转徽标消失。 相反,我们的列表将显示在页面上。

By using the JavaScript method, map(), we are able to create a new array of items by mapping over the todo items from state and displaying them by index.

通过使用JavaScript方法map() ,我们可以通过映射状态中的todo并按索引显示它们来创建新的项目数组。

Let’s create a list of items:

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

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

Navigate to your browser where React is running. You will see something like this:

导航到运行React的浏览器。 您将看到如下内容:

步骤4 —在“待办事项”列表中创建新项目 (Step 4 — Creating New Items in the To-Do List)

Now, let’s give our application the power to create a new item for our to-do app.

现在,让我们的应用程序可以为待办事项应用程序创建新项目。

While in the src/App.js file, we need to add a couple of things. At the top, we will add another component called TodoForm. In this component we want to:

src/App.js文件中,我们需要添加一些内容。 在顶部,我们将添加另一个名为TodoForm组件。 在此组件中,我们要:

  • Start with an empty state for an input field.

    从输入字段的空状态开始。
  • Be able to update the form by setting the state.

    能够通过设置状态来更新表单。
  • Handle the submit.

    处理提交。

设置表单输入的空状态 (Setting our Empty State for the Form Input)

To set our state, we will write it like so:

要设置状态,我们将这样编写:

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

The first is the “value” and the second is how we are going to be setting the state. The state starts off empty, and as we add things to our state, it will add it to our list of to-do items.

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

We will want to add in a handleSubmit variable that can handle our addTodo function (we will make that function soon) and add the item to the list. If nothing is in the input box and the user presses ENTER, we want it to not do anything (that is, not add in an empty tile to the list).

我们将要添加一个handleSubmit变量,该变量可以处理我们的addTodo函数(我们将很快制作该函数)并将该项添加到列表中。 如果输入框中没有任何内容,并且用户按ENTER ,我们希望它不执行任何操作(也就是说,不要在列表中添加空白图块)。

Adding that functionality into a form that has an input box, we will have our code look like this:

将该功能添加到具有输入框的表单中,我们的代码将如下所示:

[list src/App.js]
function TodoForm({ addTodo }) {
  const [value, setValue] = 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>
  );
}

Let’s go ahead and build the addTodo function now. Staying within App.js, under the state of the App component, the function will be able to grab the existing list of items, add on the new item, and display that new list.

现在开始构建addTodo函数。 App.jsApp.js ,在App组件的状态下,该函数将能够获取现有项目列表,添加新项目并显示该新列表。

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

Notice that there is no this.state. With the new React Hooks, we have no more need to use that, since the new Hooks understand that this.state is going to be implied in certain places.

注意,没有this.state 。 有了新的React Hooks,我们就不再需要使用它了,因为新的Hooks知道在某些地方将隐含this.state

There is a spread operator in the code as well. The three dots before the todos copy the list for us so that we are able to add on the new to-do item. Then using our keyword that we set earlier, we will set the state with setTodos.

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

By using the TodoForm down in the return of the App component, we will see that input box pop up now. The entire src/App.js file will look like this so far:

通过在App组件的返回中向下使用TodoForm ,我们将看到现在弹出输入框。 src/App.js ,整个src/App.js文件将如下所示:

src/App.js
src / App.js
import React, { useState } from "react";
import "./App.css";

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

function TodoForm({ addTodo }) {
  const [value, setValue] = 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] = useState([
    { text: "Learn about React" },
    { text: "Meet friend for lunch" },
    { text: "Build really cool todo app" }
  ]);

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

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

You can now add in a to-do item to your list in your browser.

现在,您可以在浏览器的列表中添加待办事项。

步骤5 —更新待办事项清单中的项目 (Step 5 — Updating Items in the To-Do List)

Let’s add the functionality to cross off an item on our To-Do list.

让我们添加功能以划掉待办事项列表上的项目。

更新我们的状态 (Updating Our State)

Our state in our App component needs a little extra for the “Completed” status to be able to change. We will be adding in another key/value pair to our list of objects. By adding in an “isCompleted: false” value, we will set that to false to begin with and will, when prompted, change that to true.

App组件中的状态需要一些额外的内容才能更改为“已完成”状态。 我们将在我们的对象列表中添加另一个键/值对。 通过添加“ isCompleted:false”值,我们将其设置为false开头,并在出现提示时将其更改为true。

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

We will need a function like the addTodo function, but this one will be able to “complete” an item. We will want to do some similar things that we did in addTodo, like using the spread operator to grab the current list of items. In this function, we will be changing the isCompleted status to true so that it knows it has been completed. It will then update the state and set the state to the newTodos.

我们将需要一个类似于addTodo函数的函数,但是该函数将能够“完成”一项。 我们将要做一些与addTodo相似的事情,例如使用点差运算符获取当前项列表。 在此函数中,我们将isCompleted状态更改为true ,以使其知道已完成。 然后它将更新状态并将状态设置为newTodos

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

By using completeTodo in the Todo function, we are going to be able to use that functionality. When the Complete button is clicked, it will add in the textDecoration styling and cross-out the item. We are using a ternary operator, a feature within ES6 JavaScript, which is another way of doing an if/else statement. This is our way of completing an item on the list and “updating” the list. The code will look as follows:

通过在Todo函数中使用completeTodo ,我们将能够使用该功能。 单击“ 完成”按钮时,它将添加textDecoration样式并划掉该项。 我们正在使用三元运算符 ,这是ES6 JavaScript中的一项功能,这是执行if/else语句的另一种方式。 这是我们完成列表中的项目并“更新”列表的方式。 该代码将如下所示:

src/App.js
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>
  );
}

Go down to the return of the App component and add in the following line:

转到App组件的return并添加以下行:

completeTodo={completeTodo}

The code will now look like this:

现在的代码将如下所示:

src/App.js
src / App.js
<div className="card-content">
    {todos.map((todo, index) => (
        <Todo
            key={index}
            index={index}
            todo={todo}
            completeTodo={completeTodo}
        />
    ))}
</div>

Returning to the browser, your to-do app will look like this when a “Complete” button is clicked.

返回浏览器,单击“完成”按钮,您的待办事项应用程序将如下所示。

Now we can read our list, add to our list, and update the completed status of each item. Next, we will add delete functionality.

现在,我们可以阅读列表,添加到列表中,并更新每个项目的完成状态。 接下来,我们将添加删除功能。

第6步-删除待办事项 (Step 6 — Deleting a To-Do Item)

By adding just a couple lines, we will be able to add in the functionality of deleting an item.

通过仅添加几行,我们将能够添加删除项的功能。

We will go ahead and build the removeTodo function so that when we click on an “X” to delete an item, the item will be deleted. That function will be located by the others underneath the state of the App component.

我们将继续构建removeTodo函数,以便当我们单击“ X”以删除项目时,该项目将被删除。 该功能将由其他功能定位在App组件的状态下。

In this removeTodo function, we will again be using the spread operator, but once we grab that current list, we will be splicing the chosen index off of the array of items. Once that is removed, we will return the new state by setting it with setTodos to be newTodos.

在这个removeTodo函数中,我们将再次使用散布运算符,但是一旦我们获取了当前列表,就将选择的索引从项目数组中拼接出来。 一旦被删除,我们将通过设置它返回的新状态setTodosnewTodos

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

In your Todo function, you will want to add in this line:

在您的Todo函数中,您需要添加以下行:

<button onClick={() => removeTodo(index)}>x</button>

This will look like the following:

如下所示:

src/App.js
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>
  );
}

You’ll also see that we are bringing in removeTodo at the top and then using it in the onClick of the “X”.

您还将看到我们在顶部引入了removeTodo ,然后在“ X”的onClick中使用它。

Adding in removeTodo in the Todo part of returning the App component, our “delete” will be fully functional. Add it in here:

在返回App组件的Todo部分中添加removeTodo时,我们的“删除”功能将完全可用。 在这里添加:

src/App.js
src / App.js
<Todo
    key={index}
    index={index}
    todo={todo}
    completeTodo={completeTodo}
    removeTodo={removeTodo}
/>

With that added in, go to your browser and you’ll see a button with an “X” that, when clicked, deletes the item completely.

添加该内容后,转到浏览器,您将看到带有“ X”的按钮,单击该按钮将完全删除该项目。

第7步-将应用程序整合在一起 (Step 7 — Bringing the App Together)

The entire src/App.js file will look like this in the end:

最后,整个src/App.js文件将如下所示:

src/App.js
src / App.js
import React, { useState } 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] = 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] = 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;

结论 (Conclusion)

A to-do app can be a great reminder or starting point when it comes to CRUD in web development. Being able to read information, create new information, update existing information, and delete information can be powerful in any application.

待办事项应用程序可能是Web开发中CRUD的重要提醒或起点。 能够读取信息,创建新信息,更新现有信息和删除信息在任何应用程序中都可以实现。

In this tutorial, your created a CRUD To-do list app with React Hooks, which allowed for a more straight-forward way of coding and made the code clear and concise. If you’d like to learn more about React, check out the official React docs.

在本教程中,您使用React Hooks创建了一个CRUD待办事项列表应用程序,它允许使用更直接的编码方式并使代码清晰明了。 如果您想了解更多有关React的信息,请查看官方的React文档

翻译自: https://www.digitalocean.com/community/tutorials/how-to-build-a-react-to-do-app-with-react-hooks

react-hooks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值