图文并茂教你快速入门React系列02-state

State

在React中,什么是state?

在 React 中,随时间变化的数据被称为状态(state)。你可以向任何组件添加状态,并按需进行更新。

如何添加使用state?

使用 useState Hook 为组件添加状态

例如

import { useState } from 'react';
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);

state特别之处

新的(奇怪的)知识要增加了~ 下面会做解释哦~

  • 与普通 JavaScript 变量不同,React state的行为更像一个快照。设置它并不改变你已有的状态变量,而是触发一次重新渲染。
  • 通俗来说,就是临时的,一次性的那种,第一次看到这个说实话我也很惊讶
  • 官方文档是这么解释的:React 这样工作是为了帮助你避免微妙的 bug。

举个栗子

console.log(count);  // 0
setCount(count + 1); // 请求用 1 重新渲染
console.log(count);  // 仍然是 0!

为什么出现这个问题?如何解决这个问题?

原因:一个 state 变量的值在 React 通过调用你的组件“获取 UI 的快照”时就被“固定”了, 即使其事件处理函数的代码是异步的。
解决:set的时候传入函数就OK了,举例如下

setScore(s => s + 1)

更新 state 后替换 state ,会如何运行呢?

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 5);
        setNumber(n => n + 1);
        setNumber(42);
      }}>增加数字</button>
    </>
  )
}

答案如下:

注意事项

  • 在严格模式下,React 会执行每个更新函数两次(但是丢弃第二个结果)以便帮助你发现错误。

useState Hook 功能

  • 在 React 中,useState 以及任何其他以“use”开头的函数都被称为 Hook。
  • State 变量 用于保存渲染间的数据。
  • State setter 函数 更新变量并触发 React 再次渲染组件。
  • 渲染同一个组件两次,每个副本都会有完全隔离的 state,改变其中一个不会影响另一个。

用法

对于下面代码来说:index 是一个 state 变量,setIndex 是对应的 setter 函数。

import { useState } from 'react';

const [index, setIndex] = useState(0);

使用state 处理对象和数组的数据变化

  • 创建一个新的对象(或复制现有的对象),然后用这个副本来更新状态
  • 使用 … 展开语法来复制你想改变的对象和数组

举个栗子

import { useState } from 'react';

export default function Form() {
  const [person, setPerson] = useState({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    setPerson({
      ...person,
      name: e.target.value
    });
  }

  function handleTitleChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        title: e.target.value
      }
    });
  }

  function handleCityChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        city: e.target.value
      }
    });
  }

  function handleImageChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        image: e.target.value
      }
    });
  }

  return (
    <>
      <label>
        Name:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Title:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        City:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Image:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        {' by '}
        {person.name}
        <br />
        (located in {person.artwork.city})
      </p>
      <img
        src={person.artwork.image}
        alt={person.artwork.title}
      />
    </>
  );
}

试一把这个代码吧~~

Tips: 可以使用 Immer 之类的库来减少重复代码

import { useImmer } from 'use-immer';

export default function Form() {
  const [person, updatePerson] = useImmer({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    updatePerson(draft => {
      draft.name = e.target.value;
    });
  }

  function handleTitleChange(e) {
    updatePerson(draft => {
      draft.artwork.title = e.target.value;
    });
  }

  function handleCityChange(e) {
    updatePerson(draft => {
      draft.artwork.city = e.target.value;
    });
  }

  function handleImageChange(e) {
    updatePerson(draft => {
      draft.artwork.image = e.target.value;
    });
  }

  return (
    <>
      <label>
        Name:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Title:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        City:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Image:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        {' by '}
        {person.name}
        <br />
        (located in {person.artwork.city})
      </p>
      <img
        src={person.artwork.image}
        alt={person.artwork.title}
      />
    </>
  );
}

Immer处理数组

import { useState } from 'react';
import { useImmer } from 'use-immer';

let nextId = 3;
const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [list, updateList] = useImmer(initialList);

  function handleToggle(artworkId, nextSeen) {
    updateList(draft => {
      const artwork = draft.find(a =>
        a.id === artworkId
      );
      artwork.seen = nextSeen;
    });
  }

  return (
    <>
      <h1>Art Bucket List</h1>
      <h2>My list of art to see:</h2>
      <ItemList
        artworks={list}
        onToggle={handleToggle} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

小伙伴们,先写到这里啦,我们明天再见啦~~

大家要天天开心哦

欢迎大家指出文章需要改正之处~
学无止境,合作共赢

在这里插入图片描述

欢迎路过的小哥哥小姐姐们提出更好的意见哇~~

猜你喜欢

转载自blog.csdn.net/tangdou369098655/article/details/130998678