react_2

root.render(<P4 id={1}></P4>);
状态

先来看一个例子,能否把服务器返回的数据显示在页面上

import axios from 'axios'
let count = 0
export default function P5(props: { id: number }) {
  
  function getTime() {
    const d = new Date()
    return d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds()
  }
  
  async function updateStudent() {
    const resp = await axios.get(
      `http://localhost:8080/api/students/${props.id}`
    )
    Object.assign(student, resp.data.data)
    console.log(current, student, getTime())
  }

  const current = count++
  let student = { name: 'xx' }
  console.log(current, student, getTime())
  updateStudent()
  
  return <h3>姓名是:{student.name}</h3>
}
  • count 是一个全局变量,记录 P5 函数第几次被调用

执行效果,控制台上

0 {name: 'xx'} '16:22:16'
0 {id: 1, name: '宋远桥', sex: '男', age: 40} '16:22:18'

此时页面仍显示 姓名是:xx

那么修改一下 props 的 id 呢?进入开发工具把 id 从 1 修改为 2,控制台上

1 {name: 'xx'} '16:24:0'
1 {id: 2, name: '俞莲舟', sex: '男', age: 38} '16:24:2'

此时页面仍显示 姓名是:xx

为什么页面没有显示两秒后更新的值?

  • 第一次,页面显示的是 P5 函数的返回结果,这时 student.name 还未被更新成宋远桥,页面显示 xx

    • 虽然 2s 后数据更新了,但此时并未触发函数执行,页面不变

  • 第二次,虽然 props 修改触发了函数重新执行,但既然函数重新执行,函数内的 student 又被赋值为 { name: 'xx' },页面还是显示 xx

    • 2s 后数据更新,跟第一次一样,并未重新触发函数执行,页面不变

结论:

useEffect

Effect 称之为副作用(没有贬义),函数组件的主要目的,是为了渲染生成 html 元素,除了这个主要功能以外,管理状态,fetch 数据 ... 等等之外的功能,都可以称之为副作用。

useXXX 打头的一系列方法,都是为副作用而生的,在 react 中把它们称为 Hooks

useEffect 三种用法

  • 函数是无状态的,执行完毕后,它内部用的数据都不会保存下来

  • 要想让函数有状态,就需要使用 useState 把数据保存在函数之外的地方,这些数据,称之为状态

  • useState

  • import axios from 'axios'
    import { useReducer, useState } from 'react'
    import { Student } from '../model/Student'
    let count = 0
    export default function P5(props: { id: number }) {
    
      // ...
    
      async function updateStudent() {
        const resp = await axios.get(
          `http://localhost:8080/api/students/${props.id}`
        )
        Object.assign(student, resp.data.data)
        console.log(current, student, getTime())
      }
    
      const current = count++
      let [student] = useState<Student>({ name: 'xx' })
      console.log(current, student, getTime())
      updateStudent()
    
      return <h3>姓名是:{student.name}</h3>
    }

    接下来使用 setXXX 方法更新 State

  • import axios from 'axios'
    import { useState } from 'react'
    import { Student } from '../model/Student'
    export default 
    
    function P5(props: { id: number }) {
      async function updateStudent() {
        const resp = await axios.get(`/api/students/${props.id}`)
        setStudent(resp.data.data)
      }
    
      let [student, setStudent] = useState<Student>({ name: 'xx' })
      updateStudent()
    
      return <h3>姓名是:{student.name}</h3>
    }

    工作流程如下

    首次使用 useState,用它的参数初始化 State

    2s 后数据更新,setStudent 函数会更新 State 数据,并会触发下一次渲染(P5 的调用)

    再次调用 useState,这时返回更新后的数据

    这时再返回 jsx,内容就是 姓名是:宋远桥

    P.S.

    使用了 useState 之后,会执行两次 xhr 请求,后一次请求是 react 开发工具发送的,不用理会

    问题还未结束,第二次 P5 调用时,updateStudent 还会执行,结果会导致 2s 后响应返回继续调用 setStudent,这会导致每隔 2s 调用一次 P5 函数(渲染一次)

    如何让 updateStudent 只执行一次呢?一种土办法是再设置一个布尔 State

    接下来数据更新

    第二次进入 P5 函数时,由于 fetch 条件不成立,因此不会再执行两个 setXXX 方法

    函数式组件的工作流程

  • 首次调用函数组件,返回的 jsx 代码会被渲染成【虚拟 dom 节点】(也称 Fiber 节点)

    • 此时使用 useState 会将组件工作过程中需要数据绑定到【虚拟 dom 节点】上

    • 根据【虚拟 dom 节点】会生成【真实 dom 节点】,由浏览器显示出来

  • 当函数组件的 props 或 state 发生变化时,才会重新调用函数组件,返回 jsx

    • props 变化由父组件决定,state 变化由组件自身决定

    • jsx 与上次的【虚拟 dom 节点】对比

      • 如果没变化,复用上次的节点

      • 有变化,创建新的【虚拟 dom 节点】替换掉上次的节点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码的翠花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值