])
然后我们就可以使用books
来获取数据,使用setBooks
来更新数据
// 使用setBooks更新数据,即增加书目
// params:title 书名
const addBook = (title)=>{
setBooks([…books,{title, id:uuidv4()}])
}
return (
{/* 展示数据:书目 */}
{books.map(book => {
return (
- {book.title}
)
})}
{/* 将更新书目的方法传递给子组件,让子组件执行 */}
)
由子组件辅助完成更新数据的操作:
import React, { useState } from ‘react’ // 引入必要的库
// 添加新书目
// 接收addBook方法
const AddBook = ({addBook}) => {
// 初始化title为空,即用户还未输入想要增加的书目
const [ title, setTitle ] = useState(‘’);
// 提交时,调用addBook方法,把新增的title返回
const handleSubmit = (e)=>{
e.preventDefault();
addBook(title);
setTitle(“”);
}
return (
// 用户输入书名并提交
<input type=“text” placeholder=‘书名’
onChange={(e) => setTitle(e.target.value)} value={title} />
)
}
效果:
蓝色背景就是我们初始化时写入的数据;
从文本框输入的文字,通过提交,更新到state,并展示出来
之前我们谈到React的生命周期,里面有三个比较常用的钩子函数,分别是:
- componentDidMount():会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方
- componentDidUpdate():会在更新后会被立即调用。首次渲染不会执行此方法。
- componentWillUnmount():会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
但函数组件没有生命周期,如果想要在页面渲染或更新时执行某些操作,可以使用Hooks的useEffect来完成
下面是一个小例子:
当页面加载或重新渲染(数据更新)时,打印出提示语
引入:
import React, { useState, useEffect } from ‘react’
使用:
// 当页面加载或重新渲染时,打印提示语
useEffect(()=>{
console.log(“useEffect正在执行中。。。”)
})
效果:
当页面刷新时,打印一次;
当添加了书目时,又打印了一次:
不论是哪个数据更新,都会触发useEffect的执行。如果希望useEffect只追踪某几个变量的变化,可以在useEffect的第二个参数中,传入一个数组;当数组中的变量发生改变时,useEffect就会执行
先来看看多个state时,其中一个state更新,useEffect的反应(同一个组件中可以多次使用useState)
// 另起一个用来存储年龄的state(允许多次使用useState)
const [age, setAge] = useState(22);
// 更新age
const handleClick = ()=>{
setAge(age+1);
}
// 当页面加载或重新渲染时,打印提示语
useEffect(()=>{
console.log(“useEffect正在执行中。。。”,age)
})
创建一个button按钮,点击一下,就修改age:
点击一下年龄+1
效果:
此处我修改了useEffect的输出函数,多加了年龄的打印,这样看得更清楚些。可以看到,无论是修改age还是添加书目,都会触发useEffect
然后,我们使用useEffect的第二个参数,限定useEffect的使用范围
// 添加第二个参数,当book更新时,才触发打印
useEffect(()=>{
console.log(“useEffect正在执行中。。。”,age)
},[ books ])
效果:一开始页面加载,useEffect会先执行一次;然后我点击增加age,点击两次,都是没有打印输出的(但age有在修改,点击两次,age值为24);最后我添加了书目,才有了打印。可见,限制useEffect的使用范围已生效
我们还可以在useEffect中将输入的书目进行本地存储
本地存储:localStorage
从文本框输入的书名,网页刷新后就不见了。如果我们存储起来,刷新的时候也能展示新输入的书目
- 每次数据更新时都存到localStorage:
// 本地存储 BookList.js
useEffect(()=>{
// console.log(“useEffect正在执行中。。。”)
localStorage.setItem(“books”, JSON.stringify(books));
},[ books ])
- 刷新页面时从localStorage中取出之前的数据,如果第一次加载,就展示初始化的书目即可(也就是《我们仨》《我的阿勒泰》《蒋勋说<红楼梦>》三本书):
// 刷新页面时从localStorage中取出之前的数据
const [books, dispatch] = useReducer(BookReducer, initBooks, ()=>{
const result = localStorage.getItem(‘books’);
return result ? JSON.parse(result) : initBooks
})
效果:
-
一开始加载页面,展示初始化的三本书;
-
然后我加了一本书名,页面展示4本书名;
-
最后我点击左上角的刷新,4本书名还在
接着是useContext。
Context-API获取props数据,有两种方法:
-
一种是通过contextType,只能获取离该组件最近的context,且函数组件不能使用;
-
另一种是consumer,需要包裹住想要渲染的标签,可以获取多个context。
上一篇文章中,我们嵌套使用多个context时,代码是这样的:
代码稍微长了一点
如果用useContext,就会简洁很多
import React, { Component,useContext } from ‘react’
import { ThemeContext } from ‘…/contexts/ThemeContext’;
import { GreetingContext } from ‘…/contexts/GreetingContext’;
const Navbar = ()=>{
const greetingContext = useContext(GreetingContext); // GreetingContext使用
const themeContext = useContext(ThemeContext); // ThemeContext使用
const { isAGirl, toggleGreeting } = greetingContext;
const { isLightTheme, light, dark } = themeContext;
const theme = isLightTheme ? light : dark;
return (
Context App
{ isAGirl ? ‘hello,girl~’ : ‘hello,boy~’}
总结
-
框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。
-
算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!