import axios from "axios";
import { Student } from "../model/Student";
import R from "../model/R";
import { useState } from "react";
export default function P5({ id }: { id: number }) {
async function updateStudent() {
const resp = await axios.get<R<Student>>(
`http://localhost:8080/api/students/${id}`
);
console.log(resp.data.data);
setStudent(resp.data.data);
// student.name = resp.data.data.name;
}
//updateStudent();
// const student = { name: "kk" };
const [student, setStudent] = useState({ name: "kk" });
const [fetch, setFetch] = useState<boolean>(false);
if (!fetch) {
setFetch(true);
updateStudent();
}
return <h3>{student.name}</h3>;
}
useEffect
Effect 称之为副作用(没有贬义),函数组件的主要目的,是为了渲染生成 html 元素,除了这个主要功能以外,管理状态,fetch 数据 ... 等等之外的功能,都可以称之为副作用。
useXXX 打头的一系列方法,都是为副作用而生的,在 react 中把它们称为 Hooks
useEffect 三种用法
import axios from "axios"
import { useEffect, useState } from "react"
/*
useEffect
参数1:箭头函数, 在真正渲染 html 之前会执行它
参数2:
情况1:没有, 代表每次执行组件函数时, 都会执行副作用函数
情况2:[], 代表副作用函数只会执行一次
情况3:[依赖项], 依赖项变化时,副作用函数会执行
*/
export default function P6({ id, age }: { id: number, age: number }) {
console.log('1.主要功能')
// 情况1:没有, 代表每次执行组件函数时, 都会执行副作用函数
// useEffect(() => console.log('3.副作用功能'))
// 情况2:[], 代表副作用函数只会执行一次
// useEffect(() => console.log('3.副作用功能'), [])
情况3:[依赖项], 依赖项变化时,副作用函数会执行,当id的值变化时,useEffect会重新执行
useEffect(() => console.log('3.副作用功能'), [id])
console.log('2.主要功能')
return <h3>{id}</h3>
}
用它改写 P5 案例
import axios from "axios"
import { useEffect, useState } from "react"
export default function P6({ id, age }: { id: number, age: number }) {
const [student, setStudent] = useState({name:'xx'})
useEffect(()=>{
async function updateStudent() {
const resp = await axios.get(`http://localhost:8080/api/students/${id}`)
setStudent(resp.data.data)
}
updateStudent()
// 情况3:[依赖项], 依赖项变化时,副作用函数会执行
}, [id])
return <h3>{student.name}</h3>
}
useContext
import axios from 'axios'
import { createContext, useContext, useEffect, useState } from 'react'
import { R, Student } from '../model/Student'
/*
createContext 创建上下文对象
useContext 读取上下文对象的值
<上下文对象.Provider> 修改上下文对象的值
*/
// createContext 创建上下文对象
const HiddenContext = createContext(false)
// 给以下组件提供数据,控制年龄隐藏、显示
export default function P7() {
const [students, setStudents] = useState<Student[]>([])
const [hidden, setHidden] = useState(false)
useEffect(()=>{
async function updateStudents() {
const resp = await axios.get<R<Student[]>>("http://localhost:8080/api/students")
setStudents(resp.data.data)
}
updateStudents()
}, [])
function hideOrShow() {
// 参数:上一次状态值,旧值
// 返回值:要更新的新值
setHidden((old)=>{
return !old
})
}
//<上下文对象.Provider> 修改上下文对象的值
return <HiddenContext.Provider value={hidden}>
<input type="button" value={hidden?'显示':'隐藏'} onClick={hideOrShow}/>
<P71 students={students}></P71>
</HiddenContext.Provider>
}
// 负责处理学生集合
function P71({ students }: { students: Student[] }) {
const list = students.map(s=><P72 student={s} key={s.id}></P72>)
return <>{list}</>
}
// 负责显示单个学生
function P72({ student }: { student: Student }) {
//读取上下文对象的值
const hidden = useContext(HiddenContext)
const jsx = !hidden && <span>{student.age}</span>
return <div>{student.name} {jsx}</div>
}
-
如果组件分散在多个文件中,HiddenContext 应该 export 导出,用到它的组件 import 导入
-
React 中因修改触发的组件重新渲染,都应当是自上而下的
-
setHidden 方法如果更新的是对象,那么要返回一个新对象,而不是在旧对象上做修改