【React】如何使用useState和setState创建动态页面

545 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

本文主要内容:通过一个简单的小例子,由浅入深地介绍如何使用react中的state

state是我们编写动态网页的基础,给了我们在网页运行的同时改变网页状态的途径。

state最基础也最重要的就是两个方法,useStatesetState,这篇文章将会在state是最简单的单一文本的情况下对这两个方法进行入门的介绍,至于更复杂的state情况,如数组对象等,会在之后的文章中逐一总结,本文仅作方法的介绍,顺带还会提一下三元选择表达式的用法。

项目预览

可以看到是非常简单的一个页面

image.png

用最基础的HTML语句编写

export default function App() {
  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div className="state--value">
        <h1>YES</h1>
      </div>
    </div>
  );
}

当然还要辅以一些CSS样式的帮助,就获得了想要的页面。

使用state来替换YES

本文的主要内容是要介绍state,当然不能满足于静态网页,所以接下来看一下如何能够使用state来设置变量代入YES的位置。

理解state

首先让我根据我的理解来具象化一下state,从状态机的视角来看,这就是整个网页目前的状态;而用程序的视角来看,就是可以理解为一个静态全局变量,对应的组件能对其进行修改,这个被修改的值也会扩展到全局。

我们可以将上面的代码改成下面的样子

export default function App() {
  const answer="YES";
  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div className="state--value">
        <h1>{answer}</h1>
      </div>
    </div>
  );
}

看到定义了一个常量answer,并且将其渲染到了<h1>标签上,{}是react中解析js语句的方法

它作为常量是无法在网页运行时修改的,即我们所说的静态网页。然而使用state就能使得这个定义的answer有办法在网页运行时修改,并且重新渲染。

使用useState()定义变量

将上面代码的YES先换回来,主要看下面代码中的useState()方法

import React from "react"

export default function App() {
  const answer=React.useState("YES");
  console.log(answer)
  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div className="state--value">
        <h1>YES</h1>
      </div>
    </div>
  );
}

可以看到打印出来的answer是个数组,我们设置的值"YES"在第一个,而第二个是一个函数 image.png 所以我们想要使用我们设置的值,就应该对answer数组进行选取,也就是可以得到如下代码

import React from "react"

export default function App() {
  const answer=React.useState("YES");
  console.log(answer)
  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div className="state--value">
        <h1>{answer[0]}</h1>
      </div>
    </div>
  );
}

使用setAnswer改变变量

接下来我们要对answer进行修改,这就会用到setState的方法。

我们可以从上面一段里知道,useState后会产生的数组的第二项是一个函数,而这就是我们要使用setState对应的函数,可以给它设置成任何名字,funcsetStateblabla,但是一般我们前面设置了变量名为answer,那么就设置这个函数为setAnswer

所以我们可以得到重新的定义方式如下

const [answer, setAnswer]=React.useState("YES");

这样answer对应"YES"setAnswer对应answer的set函数

那么接下来的问题就是如何使用这个setAnswer

不考虑先前状态

setAnswer也有着两种情况,这里先说明第一种比较简单的情况

首先给页面上的元素添加一个事件,然后在这个事件的函数里就能使用setAnsweranswer进行修改,所以我写了如下的代码

import React from "react"

export default function App() {
  const [answer, setAnswer]=React.useState("YES");
  function handleClick(){
    return(setAnswer("NO"))
  }
  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div className="state--value" onClick={handleClick}>
        <h1>{answer}</h1>
      </div>
    </div>
  );
}

在圆圈对应的div上添加了onClick事件,绑定了函数handleClick,在函数里使用了setAnswer

所以结果预览如下,我们实现了在网站运行的过程中将answer的值从YES改为了NO

7uoj6-r6bj4.gif

考虑先前状态

可以看到我们虽然实现了YES变成NO,但是如果又改主意了却没有办法变回YES

所以我们可以选择使用一个非的操作来实现YES和NO的转变。

然而这又涉及到了一个问题,我们并不能对YES进行非的运算来变成NO,于是可以想到利用三元表达式将true进行映射来选择YES或者NO

因为我想保持文章的连贯性,所以将三元表达式放在最后写,这里还是先写一下如何在setAnswer中进行truefalse的相互转换。

这里就需要用到下面的代码段

const [isGoingOut, setIsGoingOut]=React.useState(true);
function handleClick(){
    return(setIsGoingOut(prevState => !prevState))
}

可以知道在setIsGoingOut中,prevState会接收先前的状态,即isGoingOut先前的值,然后会更新成箭头函数对应的后面的值,!prevState!isGoingOut

结果预览如下,在控制台输出isGoingOut的值,可以看到在我点击的时候turefalse交替输出

to8dz-en0k3.gif

使用三元表达式转换Boolean

我们最终的结果是要将值在页面上输出出来,所以就涉及了ture转换成YESfalse转换成NO的需求,而这可以用一行三元表达式非常简洁地写出来。

它的基础语法示意如下

condition ? exprIfTrue : exprIfFalse

如果问号前的条件为真,选择冒号前的选项,否则选择冒号后面的选项,那么我们就可以写出下面的代码来最终实现效果

import React from "react"

export default function App() {
  const [isGoingOut, setIsGoingOut]=React.useState(true);
  function handleClick(){
    return(setIsGoingOut(prevState => !prevState))
  }
  return (
    <div className="state">
      <h1 className="state--title">Do I feel like going out tonight?</h1>
      <div className="state--value" onClick={handleClick}>
        <h1>{isGoingOut ? "Yes" : "No"}</h1>
      </div>
    </div>
  );
}

可以看到上面的代码在<h1>标签中写了一个{}解释的三元表达式,isGoingOuttrue时会展示YES

当然也可以先在return上面定义一个answer,然后利用三元表达式进行赋值,在其获得YES或者NO 之后再渲染到<h1>标签上。不过这种方法显然没有上面的代码简洁,所以不再赘述

看一下最终效果

ccdze-1z3kk.gif