入门 React Hooks --- 小案例

125 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hook 这个单词的意思是"钩子"。

React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。 React Hooks 就是那些钩子。

你需要什么功能,就使用什么钩子。React 默认提供了一些常用钩子,你也可以封装自己的钩子。

所有的钩子都是为函数引入外部功能,所以 React 约定,钩子一律使用use前缀命名,便于识别。你要使用 xxx 功能,钩子就命名为 usexxx。

在 src 下新建 TemperatureControl 文件夹。项目目录如下:

|-TemperatureControl
    |-index.js
    |-index.css

在 App.js 文件中引入 TemperatureControl 组件。

App.js

import TemperatureControl from './TemperatureControl';

function App() {
  return (
    <div className="App">
      <TemperatureControl />
    </div>
  );
}

export default App;

TemperatureControl / index.js

import React from 'react';
import './index.css';

const TemperatureControl = () => {
  return (
    <div className='app-container'>
      <div className='temperature-display-container'>
        <div className='temperature-display'>10°C</div>
      </div>
      <div className='button-container'>
        <button>+</button>
        <button>-</button>
      </div>
    </div>
  );
};

export default TemperatureControl;

index.css

body {
  font-family: sans-serif;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  min-height: 100vh;
}

.app-container {
  height: 400px;
  width: 300px;
  background: #2b5870;
  border-radius: 20px;
  box-shadow: 10px 10px 38px 0px rgba(0, 0, 0, 0.75);
  margin-top: 100px;
}

.temperature-display-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 70%;
}

.temperature-display {
  display: flex;
  border-radius: 50%;
  color: #ffffff;
  height: 220px;
  width: 220px;
  text-align: center;
  justify-content: center;
  align-items: center;
  font-size: 48px;
  border: 3px #ffffff solid;
  transition: background 0.5s;
}

button {
  border-radius: 100px;
  height: 80px;
  width: 80px;
  font-size: 32px;
  color: #ffffff;
  background: rgb(105, 104, 104);
  border: 2px #ffffff solid;
}

button:hover {
  background: rgb(184, 184, 184);
  cursor: pointer;
}

button:focus {
  outline: 0;
}

.button-container {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
}

.neutral {
  background: rgb(184, 184, 184);
}

.cold {
  background: #035aa6;
}

.hot {
  background: #ff5200;
}

图片.png

动态显示温度值——使用 State

首先我们让温度值动态显示。将温度值存储在 state 内,便于我们稍后读取数据,并用于逻辑呈现。 建议把引起 UI 改变的东西都放在 state 里。 在 index.js 文件开头导入 useState hook:

import React, { useState } from 'react';

在 function 函数内添加:

const [temperatureValue, setTemperatureValue] = useState(10);

我们通过 useState 进行组件状态管理。useState hook 包含两个参数: 一个表示状态初始值的变量 一个更新状态值的函数 在这个例子中,我们调用了状态变量 temperatureValue 和函数 setTemperatureValue,将 10 这个值传递给 useState hook,作为 temperatureValue 的初始值。 现在我们把这个状态值用到代码里。 将 JSX 里的固定的温度值改为状态变量。这是原来的值:

<div className='temperature-display'>10°C</div>

改成这样:

<div className='temperature-display'>{temperatureValue}°C</div>

注意我们使用 {} 来渲染 temperatureValue 变量。现在,如果温度值改变,组件将重新渲染,显示新的温度值。

index.js

import React, { useState } from 'react';

const App = () => {
    const [temperatureValue, setTemperatureValue] = useState(10);

    return (
        <div className='app-container'>
            <div className='temperature-display-container'>
                <div className='temperature-display'>{temperatureValue}°C</div>
            </div>
            <div className='button-container'>
                <button>+</button>
                <button>-</button>
            </div>
        </div>
    );
};

export default App;

现在,如果你运行 app,浏览器中的一切好像跟之前一样。 但是,如果你将传递给 useState hook 的初始值从 10 改为其他(比如 15),你会看到 app 更新了,也就是说状态钩子起作用了! 按键时更改状态 接下来,我们要在按按钮时升高或降低温度。 useState hook 有一个 setTemperatureValue 函数,可以修改温度值,所以我们可以在按钮的 onClick 事件中用到它。 首先把“+”按钮的代码修改成:

 <button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>

注意它是怎么调用 setTemperatureValue 函数的。获得当前温度值,加上 1,然后将其作为参数传递。 因为温度初始值是 10,加上 1 的话状态值就变成 11。再按一次按钮,状态值变成 12...... 将“-”按钮的代码修改成:

 <button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>

和对“+”按钮的操作类似,不过这次是降低温度值。 现在我们的代码是这样的:

import React, { useState } from 'react';

const App = () => {
    const [temperatureValue, setTemperatureValue] = useState(10);

    return (
        <div className='app-container'>
            <div className='temperature-display-container'>
                <div className='temperature-display'>{temperatureValue}°C</div>
            </div>
            <div className='button-container'>
                <button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>
                <button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>
            </div>
        </div>
    );
};

export default App;

试着在浏览器运行代码,点击按钮,温度值会升高或降低。 基于状态修改颜色 接下来我们做点有意思的东西——根据温度的高低显示不同的背景色。 如果温度是 15℃ 或以上,背景色是红色;反之,背景色是蓝色。 在 CSS 里,我写了这两个类: .cold 将背景色设置为蓝色 .hot 将背景色设置为红色 将其中一个类添加至 temperature display div,会改变背景色,比如:

<div className='temperature-display cold'>{temperatureValue}°C</div>

背景色是蓝色

<div className='temperature-display hot'>{temperatureValue}°C</div>

背景色是红色 那么,怎么基于状态动态地应用这两个类呢? 创建另一个状态钩子,存放 temperatureColor:

const [temperatureColor, setTemperatureColor] = useState('cold');

注意我们给 temperatureColor 状态对象设置初始值为 “cold”(因为初始温度值为 10,我们希望背景色是蓝色)。 然后我们使用模板常量动态地添加需要的类:

<div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>

这样一来,创建一个字符串,动态应用 temperatureColor 变量。当 temperatureColor 变成 “hot” 的时候,组件会重新渲染,给 className 字符串添加 “hot” 类。 我们的代码目前是这样的:

import React, { useState } from 'react';

const App = () => {
    const [temperatureValue, setTemperatureValue] = useState(10);
    const [temperatureColor, setTemperatureColor] = useState('cold');

    return (
        <div className='app-container'>
            <div className='temperature-display-container'>
                <div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
            </div>
            <div className='button-container'>
                <button onClick={() => setTemperatureValue(temperatureValue + 1)}>+</button>
                <button onClick={() => setTemperatureValue(temperatureValue - 1)}>-</button>
            </div>
        </div>
    );
};

export default App;

将初始 temperatureColor 状态变量改为 “hot” 或 “cold”,显示板的背景色随之改变。 我们已经有一个 onClick 事件可更改 temperatureValue 的值,现在我们给这个事件增加新的逻辑。 目前 onClick 事件有一个内联函数。对于单行函数来说用内联函数比较好。但是如果是有不同逻辑的多行函数,最好是将函数放到 JSX 外面,让代码更清晰。 将下列代码粘贴到状态下面:

const increaseTemperature = () => {
    setTemperatureValue(temperatureValue + 1);
};

const decreaseTemperature = () => {
    setTemperatureValue(temperatureValue - 1);
};

这里我们定义了两个函数,用于升高或降低温度。 接下来,修改按钮的 onClick 属性,调用这些函数:

 <button onClick={increaseTemperature}>+</button>
    <button onClick={decreaseTemperature}>-</button>

我们的代码目前是这样:

const decreaseTemperature = () => {
    const newTemperature = temperatureValue - 1;
    setTemperatureValue(newTemperature);
    if (newTemperature < 15) {
        setTemperatureColor('cold');
    }
};
 import React, { useState } from 'react';

const App = () => {
    const [temperatureValue, setTemperatureValue] = useState(10);
    const [temperatureColor, setTemperatureColor] = useState('cold');

    const increaseTemperature = () => {
        setTemperatureValue(temperatureValue + 1);
    };

    const decreaseTemperature = () => {
        setTemperatureValue(temperatureValue - 1);
    };

    return (
        <div className='app-container'>
            <div className='temperature-display-container'>
                <div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
            </div>
            <div className='button-container'>
                <button onClick={increaseTemperature}>+</button>
                <button onClick={decreaseTemperature}>-</button>
            </div>
        </div>
    );
};

export default App;

注意其实没啥改变,我们只是重新构造了代码,为接下来的工作做准备。 现在就更容易为点击按钮事件添加逻辑了。 给 increaseTemperature 函数添加逻辑:

const increaseTemperature = () => {
    const newTemperature = temperatureValue + 1;
    setTemperatureValue(newTemperature);

    if (newTemperature >= 15) {
        setTemperatureColor('hot');
    }
};

当我们点击按钮若干次,temperatureValue 等于或大于 15℃ 时,temperatureColor 变量会更改,组件重新渲染,给显示板添加 “hot” 类。 降低温度时的逻辑是类似的: app 最终的代码如下:

import React, { useState } from 'react';

const App = () => {
    const [temperatureValue, setTemperatureValue] = useState(10);
    const [temperatureColor, setTemperatureColor] = useState('cold');

    const increaseTemperature = () => {
        const newTemperature = temperatureValue + 1;
        setTemperatureValue(newTemperature);

        if (newTemperature >= 15) {
            setTemperatureColor('hot');
        }
    };

    const decreaseTemperature = () => {
        const newTemperature = temperatureValue - 1;
        setTemperatureValue(newTemperature);
        if (newTemperature < 15) {
            setTemperatureColor('cold');
        }
    };

    return (
        <div className='app-container'>
            <div className='temperature-display-container'>
                <div className={`temperature-display ${temperatureColor}`}>{temperatureValue}°C</div>
            </div>
            <div className='button-container'>
                <button onClick={increaseTemperature}>+</button>
                <button onClick={decreaseTemperature}>-</button>
            </div>
        </div>
    );
};

export default App;

在这里插入图片描述