< 关於 React: 开始打地基| useState()>

09-08-2021

本章内容
  • THE STATE HOOK
    • Hook 可以做的事情
    • 规则
      • 使用useState()改变背景颜色
  • 初始化状态(Initialize State)
    • 三种影响conponent 的方式
  • 在JSX外设置状态
  • 使用之前的状态设置

THE STATE HOOK

Hook 可以做的事情:

  1. 在components 可以多次使用
  2. 简化复杂的逻辑,重新组织重点
  3. 避免混淆 this 的行爲
  4. 避免 class constructors 、 binding methods,或更高级的js 行为

规则:

  1. 只从React functions去调用
  2. 只在顶层调用 Hooks,以确保每次渲染组件时以相同的顺序调用 Hooks。
  3. 要避免的常见错误是在循环、条件或嵌套函数内调用 Hook。
// Instead of confusing React with code like this:
if (userName !== '') {
 useEffect(() => {
   localStorage.setItem('savedUserName', userName);
 });
}
 
// We can accomplish the same goal, while consistently calling our Hook every time:
useEffect(() => {
 if (userName !== '') {
   localStorage.setItem('savedUserName', userName);
 }
});

使用useState()改变背景颜色

const [color, setColor] = useState();

当前状态(current state) - 范例中的color
更新状态的函数(state setter) - 范例中的setColor

import React, { useState } from 'react';

export default function ColorPicker() {
  const [color, setColor] = useState();

 const divStyle = {backgroundColor: color};

  return (
    <div style={divStyle}>
      <p>The color is {color}</p>
      <button onClick={() => setColor('Aquamarine')}>
        Aquamarine
      </button>
      <button onClick={() => setColor('BlueViolet')}>
        BlueViolet
      </button>
      <button onClick={() => setColor('Chartreuse')}>
        Chartreuse
      </button>
      <button onClick={() => setColor('CornflowerBlue')}>
        CornflowerBlue
      </button>
    </div>
  );
}

import React, { useState } from 'react';

export default function ColorPicker() {
  const [color, setColor] = useState();
  1. import 使用方法从React函式库中去调用 {useState} 的方法
  2. 使用方式要放在 function 中
  3. 定义useState()的方法
const [color, setColor] = useState();

初始化状态(Initialize State)

三种影响conponent 的方式

  1. 第一次渲染期间,使用初始状态参数。
  2. 当 state setter 被调用时,React 会忽略初始状态参数并使用新值。
  3. 当组件由於任何其他原因重新渲染时,React 会继续使用与之前渲染相同的值。
import React, { useState } from 'react';

const colorNames = ['Aquamarine', 'BlueViolet', 'Chartreuse', 'CornflowerBlue', 'Thistle', 'SpringGreen', 'SaddleBrown', 'PapayaWhip', 'MistyRose'];

export default function ColorPicker() {
  const [color, setColor] = useState("Tomato");

 const divStyle = {backgroundColor: color};

  return (
    <div style={divStyle}>
      <p>Selected color: {color}</p>
      {colorNames.map((colorName)=>(
        <button 
          onClick={() => setColor(colorName)} 
          key={colorName}>
       	     {colorName}
      	</button>
      ))}
    </div>
  );
}


map使用方法

在初次页面使用 "Tomato" 作为初始化的页面颜色

export default function ColorPicker() {
  const [color, setColor] = useState("Tomato");

 const divStyle = {backgroundColor: color};

在JSX外设置状态

常见的模式

const handleChange = (event) => {
  const newEmail = event.target.value;
  setEmail(newEmail);
}

也可以这样简化

const handleChange = (event) => setEmail(event.target.value);

或是使用解构的方式

const handleChange = ({target}) => setEmail(target.value);

范例:

import React, { useState } from "react";

// regex to match numbers between 1 and 10 digits long
const validPhoneNumber = /^\d{1,10}$/;

export default function PhoneNumber() {
  const [phone, setPhone] = useState('');
  
   const handleChange = ({ target })=> {
     const newPhone = target.value;
     const isValid = validPhoneNumber.test(newPhone);
     if (isValid) {
       setPhone(newPhone);
     }
     // just ignore the event, when new value is invalid
    };

  return (
    <div className='phone'>
      <label for='phone-input'>Phone: </label>
      <input value={phone} onChange={handleChange} id='phone-input' />
    </div>
  );
}

在value 有更动的时候会去执行onChang{handleChange}

<input value={phone} onChange={handleChange} id='phone-input' />
    </div>

使用之前的状态设置

import React, { useState } from 'react';

export default function QuizNavBar({ questions }) {
  const [questionIndex, setQuestionIndex] = useState(0);

  const goBack = () =>
    setQuestionIndex((prevQuestionIndex) => prevQuestionIndex - 1);
    
  const goToNext = () =>
    setQuestionIndex((prevQuestionIndex) => prevQuestionIndex + 1);

  const onFirstQuestion = questionIndex === 0;
  // 起始值是0
  const onLastQuestion = questionIndex === questions.length - 1;
  // 回到上一个问题,等於问题-1

  return (
    <nav>
      <span>Question #{questionIndex + 1}</span>
      <div>
        <button onClick={goBack} disabled={onFirstQuestion}>
        // 点击上一步,或是在等於0的时候无法使用
          Go Back
        </button>
        <button onClick={goToNext} disabled={onLastQuestion}>
        // 点击往下一步,或是在最後一个无法使用
          Next Question
        </button>
      </div>
    </nav>
  );
}


<<:  Day3:第一个 Coroutine 程序

>>:  D8 - 如何用 Google Apps Script 将 Google Calendar 上的事件与更新全部列出到 Google Sheet 上?

伸缩自如的Flask [day 8] ajax with jquery

在[day 7]使用form tag 来进行submit的时候,不知道大家心里会不会有个疑问? 我要...

Day29_CSS3

突然回到CSS好像有点跳tone,主要是因为在CSS & Javascript的基础不够熟练...

[Day 28]-【STM32系列】实作-伺服马达 SG- 90 PWM控制

SG-90转起来! 今天要来玩伺服马达~ 我们使用 SG-90 透过PWM控制 精准控制角度从0° ...

Day 25 - 介绍 OSPF

今天我们来配 OSPF。 OSPF 是一种 IGP (Interior Gateway Protoc...

OpenStack Glance 介绍

本系列文章同步发布於笔者网站 在经过了好几篇的 Neutron 之後我们终於来到下一个 OpenSt...