react萌新的读书小笔记(二)
useReducer
import React, {useReducer} from 'react'
function reducer(state, action) {
switch (action.type) {
case 'changeName':
return {...state, name: action.value}
case 'changeAge':
return {...state, age: action.value}
case 'changeSex':
state.sex+=1;
return {...state }
default:
throw Error('报错啦')
}
}
export default function App() {
const [{name, age}, dispatch] = useReducer(reducer, {name:'',age:''});
return <div>
<input type="text"
value={name}
onChange={e => dispatch({type: 'changeName', value: e.target.value})}
/>
<p>{name}</p>
<input type="text"
value={age}
onChange={e => dispatch({type: 'changeAge', value: e.target.value})}
/>
<p>{age}</p>
<button onClick={()=>dispatch({type:'changeSex'})}>+</button>
{sex}
</div>
}
onChange 监听
onBlur 失去焦点
useState
复杂类型的操作
export default function App() {
let [num, setNum] = useState([]);
const add1 = () => {
setNum([...num, {
value: num.length
}])
}
const add2 = () => {
setNum([...num.reverse()])
}
return <>
<ul>
{num.map((v, i) =>
(<li key={i}>{v.value}</li>))}
</ul>
<button onClick={() => add1()}>push</button>
<br/>
<button onClick={() => add2()}>reverse</button>
</>
}
高阶方式
export default function App() {
let [num, setNum] = useState({
first: 0,
})
const clickOne = str => {
setNum({...num, [str]: num.first + 1})
}
return <>
<button onClick={() => clickOne('first')}>First {num.first}</button>
</>
}
组件通信
无状态父=>无状态子
父
export const Four = (props) => {
const list = [
{ title: 'A Christmas Carol', author: 'Charles Dickens' },
{ title: 'The Mansion', author: 'Henry Van Dyke' }];
const clicks = (e) => {
console.log(e.target.value);
}
return (<>
xxx
{list.map((v,i)=>{
return <Fill title={v.title} author={v.author} inputChange={clicks} key={i}/>
})}
</>)
}
=========
const Fill = props => {
return (<>
{/*<App/>*/}
<h1>{props.title}</h1>
<h1>{props.author}</h1>
<input type="text" onChange={props.inputChange}/>
</>)
}
useState 实现增删改
import React, {useState} from 'react';
import Headers from "./header/header";
function App() {
const [articles, setArticles] = useState([{
id: 1,
name: 'name1',
hide: true
}, {
id: 2,
name: 'name2',
hide: true
}, {
id: 3,
name: 'name3',
hide: true
}])
const deleteAti = (id) => {
setArticles(articles.filter(val => val.id !== id))
}
const addAti = () => {
let id = articles.slice(-1)[0].id + 1;
setArticles([
...articles,
{
id: id,
name: 'name' + id,
hide: true
}
])
}
const hideEdit = id => {
let update=[...articles];
let index = articles.findIndex(val => val.id===id);
let hide=articles[index].hide;
update[index]={...articles[index],hide: !hide}
return setArticles(update)
}
return (<div>
<Headers/>
<ul>
{articles.map((v, i) => {
return <li key={i}>
{v.hide&&(<div>{v.name}</div>)}
<button onClick={() => deleteAti(v.id)}>删除</button>
<button onClick={() => addAti(v.id)}>增加</button>
<button onClick={()=>hideEdit(v.id)}>隐藏</button>
</li>
})}
</ul>
</div>
);
}
export default App;
生命周期
getDerivedStateFromProps 接受新属性
render setState 发生变化
componentDidMount 调用DOM
shouldComponentUpdate
- 提高性格(为啥)
实例被创建并插入DOM中时,经历的生命周期
getDerivedStateFromProps
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
static getDerivedStateFromProps(props, state)
当prop static发生变化
export default class Headers extends Component {
state = {
error: null,
users: []
}
constructor(props) {
super(props);
}
static defaultProps = {
loading: 'loading'
}
componentDidMount() {
setTimeout(()=>{
this.setState({
error: null, users: [
{id: 1, sex: '男1'},
{id: 2, sex: '男2'},
{id: 3, sex: '男3'},
{id: 4, sex: '男4'},
]
})
},5000)
}
static getDerivedStateFromProps(props, state) {
return {...state, loading: state.users.length === 0 ? props.loading : null}
}
render() {
let {loading, users} = this.state;
return <>
<h1>headers</h1>
{loading&&<div>loading</div>}
<ul>
{users.map((v,i)=>{
return <li key={i}>{v.sex}</li>
})}
</ul>
</>
}
}
shouldComponentUpdate
返回等于true或者false,true指的是进行重新渲染,false指的是不需要重新渲染
shouldComponentUpdate(nextProps, nextState, nextContext) {
// 变化后的新数据,比如 5s后更新的数据
console.log(nextProps);
console.log(nextState);
return true
}
getSnapshotBeforeUpdate
DOM可能发生改变捕获某些信息
getSnapshotBeforeUpdate
和 componentDidUpdate
应该一起用,不然报错
当DOM发生变化的时候会触发这个生命周期
getSnapshotBeforeUpdate(prevProps, prevState) {
// 这个是dom 发生变化的时候,返回前面的prop,state 的状态
console.log(prevProps);
console.log(prevState);
return null
}
componentDidUpdate(){
}
案例
export default class Headers extends Component {
state = {
error: null,
users: []
}
constructor(props) {
super(props);
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(prevProps);
console.log(prevState);
return null
}
componentDidUpdate(){
}
static defaultProps = {
loading: 'loading'
}
componentDidMount() {
setTimeout(()=>{
this.setState({
error: null, users: [
{id: 1, sex: '男1'},
{id: 2, sex: '男2'},
{id: 3, sex: '男3'},
{id: 4, sex: '男4'},
]
})
},5000)
}
static getDerivedStateFromProps(props, state) {
return {...state, loading: state.users.length === 0 ? props.loading : null}
}
render() {
let {loading, users} = this.state;
return <>
<h1>headers</h1>
{loading&&<div>loading</div>}
<ul>
{users.map((v,i)=>{
return <li key={i}>{v.sex}</li>
})}
</ul>
</>
}
}
我们会发现当数据添加上去的时候,返回的之前的props,state
{loading: "loading"}
{error: null, users: Array(0), loading: "loading"}
getSnapshotBeforeUpdate和componentDidUpdate一起使用
可以理解用处,类似做拿到上一次的状态进行操作
getSnapshotBeforeUpdate(prevProps, prevState) {
return {foo:1}
}
componentDidUpdate(prevProps, prevState, snapshot){
console.log(snapshot);
// {foo: 1} 当数据更新的时候,或者数据发生变化的时候
}
// 从上级传过来的return,第三个参数componentDidUpdate
拿到DOM节点
constructor(props) {
super(props);
this.textInput=React.createRef();
}
<div ref={this.textInput}></div>
当数据更新时,给更新的dom添加背景颜色
getSnapshotBeforeUpdate(prevProps, prevState) { 1
//拿到dom节点
// console.log(this.textInput.current );
//这个拿到之前的状态
console.log(this.textInput.current.offsetHeight);
return {boxColor:this.textInput.current.offsetHeight>20}
}
componentDidUpdate(prevProps, prevState, snapshot){ 2
// 这个是拿到更新后的状态
console.log(this.textInput.current.offsetHeight);
}
分析,我们会发现当数据更新了,1拿到的是没有更新前的dom,2拿到了更新后的dom,1和2可以根据状态进行更新值
报错边界
请使用 static getDerivedStateFromError()
渲染备用 UI ,使用 componentDidCatch()
打印错误信息
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = {
hasError: false
}
}
componentDidCatch(err, info) {
this.setState({hasError: true})
}
render() {
if(this.state.hasError) {
return (
<div>Error occurred.</div>
)
} else {
return this.props.children
}
}
}
<ErrorBoundary>
<App />
</ErrorBoundary>
比如页面报错了,直接让他显示报错的页面
跟try catch
类似
区别
getDerivedStateFromError()
渲染备用UIcomponentDidCatch()
打印错误信息
类型 | getDerivedStateFromError | componentDidCatch |
---|---|---|
指令其他操作 | 不可以 | 可以 |
调用时间 | 渲染阶段调用 | "提交"阶段被调用 |
参数 | err | err,info |
componentWillUnmount
卸载和销毁组件的生命周期
组件dom传递
let app1=<h1>app1</h1>
let app2=<h1>app2</h1>
<Headers {...{app1,app2}}/>
===========
export default class Headers extends Component {
render() {
let {app1,app2}=this.props
return <>
{app1}
{app2}
</>
}
}
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬