终于搞懂 React Hooks了!!!!! | 您所在的位置:网站首页 › useref和usestate区别 › 终于搞懂 React Hooks了!!!!! |
学习总结!
从三个纬度学习记录: 为什么🤔️ 怎么用🔨 知识点⛽️ useState 为什么要使用useState?useState 的出现是 : 在函数组件里面使用 class的setState,刺激! 解决了的问题是:当我们一个函数组件想要有自己维护的state的时候,不得已只能转换成class。这样很麻烦! 如何使用useState? const [name, setName] = useState('rose') 复制代码useState踩坑知识点😄1. 重点: useState的初始值,只在第一次有效 我当时反正没有当回事,直到遇到了坑... 🌰2. 举个例子: 当我点击按钮修改name的值的时候,我发现在Child组件, 是收到了,但是并没有通过useState赋值给name! 结论: 实践检验知识点!😭 const Child = memo(({data}) =>{ console.log('child render...', data) const [name, setName] = useState(data) return ( child {name} --- {data} ); }) const Hook =()=>{ console.log('Hook render...') const [count, setCount] = useState(0) const [name, setName] = useState('rose') return( {count} setCount(count+1)}>update count setName('jack')}>update name ) } 复制代码useEffect 为什么要使用useEffect?useEffect 的出现是 : 在函数组件里面使用 class的生命周期函数,还是所有函数的合体!刺激! 如何使用useEffect? useEffect(()=>{ ... }) 复制代码useEffect知识点合集😄1.只在第一次使用的componentDidMount,可以用来请求异步数据...、 useEffect最后,加了[]就表示只第一次执行 useEffect(()=>{ const users = 获取全国人民的信息() },[]) 复制代码😄2.用来替代willUpdate等每次渲染都会执行的生命函数 useEffect最后,不加[]就表示每一次渲染都执行 useEffect(()=>{ const users = 每次都获取全国人民的信息() }) 复制代码😄3.每次渲染都执行感觉有点费,所以: useEffect最后,加[],并且[]里面加的字段就表示,这个字段更改了,我这个effect才执行 useEffect(() => { const users = (name改变了我才获取全国人民的信息()) },[name]) 复制代码😄4.如果我想要分别name和age呢: 可以写多个useEffect useEffect(() => { const users = (name改变了我才获取全国人民的name信息()) },[name]) useEffect(() => { const users = (name改变了我才获取全国人民的age信息()) },[age]) 复制代码😄5.如果我们之前订阅了什么,最后在willUnMount这个生命周期里面要取消订阅,这可咋用useEffect实现啊: 在effect的return里面可以做取消订阅的事 useEffect(() => { const subscription = 订阅全国人民吃饭的情报! return () => { 取消订阅全国人民吃饭的情报! } },[]) 复制代码为什么要取消订阅? 大家都知道,render了之后会执行重新useEffect,如果useEffect里面有一个每setInterval...那么每次render了,再次执行useEffect就会再创建一个setInterval,然后就混乱了...可以把下面案例return的内容删掉感受下 useEffect(() => { console.log('use effect...',count) const timer = setInterval(() => setCount(count +1), 1000) return ()=> clearInterval(timer) }) 复制代码😄6.useEffect的一些暗戳戳的规则: 1.useEffect 里面使用到的state的值, 固定在了useEffect内部, 不会被改变,除非useEffect刷新,重新固定state的值 const [count, setCount] = useState(0) useEffect(() => { console.log('use effect...',count) const timer = setInterval(() => { console.log('timer...count:', count) setCount(count + 1) }, 1000) return ()=> clearInterval(timer) },[]) 复制代码2.useEffect不能被判断包裹 const [count, setCount] = useState(0) if(2 < 5){ useEffect(() => { console.log('use effect...',count) const timer = setInterval(() => setCount(count +1), 1000) return ()=> clearInterval(timer) }) } 复制代码3.useEffect不能被打断 const [count, setCount] = useState(0) useEffect(...) return // 函数提前结束了 useEffect(...) } 复制代码具体原因跟到useEffect的生成执行规则有关系:看文档去! useRef 为什么要使用useRef?前面提到的: useEffect 里面使用到的state的值, 固定在了useEffect内部, 不会被改变,除非useEffect刷新,重新固定state的值 const [count, setCount] = useState(0) useEffect(() => { console.log('use effect...',count) const timer = setInterval(() => { console.log('timer...count:', count) setCount(count + 1) }, 1000) return ()=> clearInterval(timer) },[]) 复制代码useEffect里面的state的值,是固定的,这个是有办法解决的,就是用useRef,可以理解成useRef的一个作用: 就是相当于全局作用域,一处被修改,其他地方全更新... 如何使用useRef? const countRef = useRef(0) 复制代码useRef知识点合集😄 1. 就是相当于全局作用域,一处被修改,其他地方全更新... const [count, setCount] = useState(0) const countRef = useRef(0) useEffect(() => { console.log('use effect...',count) const timer = setInterval(() => { console.log('timer...count:', countRef.current) setCount(++countRef.current) }, 1000) return ()=> clearInterval(timer) },[]) 复制代码😄 2. 普遍操作,用来操作dom const btnRef = useRef(null) click me 活学活用,记得取消绑定事件哦! return ()=> btnRef.current.removeEventListener('click',onClick, false) const Hook =()=>{ const [count, setCount] = useState(0) const btnRef = useRef(null) useEffect(() => { console.log('use effect...') const onClick = ()=>{ setCount(count+1) } btnRef.current.addEventListener('click',onClick, false) return ()=> btnRef.current.removeEventListener('click',onClick, false) },[count]) return( {count} click me ) } 复制代码useMemo 为什么要使用useMemo?举个🌰: const Child = memo(({data}) =>{ console.log('child render...', data.name) return ( child {data.name} ); }) const Hook =()=>{ console.log('Hook render...') const [count, setCount] = useState(0) const [name, setName] = useState('rose') const data = { name } return( {count} setCount(count+1)}>update count ) } 复制代码当我们点击按钮更新count的时候,Effect组件会render,一旦render, 执行到这一行代码: const data = { name } 复制代码这一行代码会生成有新的内存地址的对象,那么就算带着memo的Child组件,也会跟着重新render, 尽管最后其实Child使用到的值没有改变! 这样就多余render了,感觉性能浪费了!于是useMemo 作为一个有着暂存能力的,就来了。 如何使用useMemo? const data = useMemo(()=>{ return { name } },[name]) 复制代码的时候,就会先根据[name]里面的name值判断一下,因为useMemo 作为一个有着暂存能力的,暂存了上一次的name结果。 结果一对比上一次的name,我们发现name值居然没有改变!那么这次data就不重新赋值成新的对象了! 没有新的对象,就没有新的内存地址,那么Child就不会重新render! const Child = memo(({data}) =>{ console.log('child render...', data.name) return ( child {data.name} ); }) const Hook =()=>{ console.log('Hook render...') const [count, setCount] = useState(0) const [name, setName] = useState('rose') const data = useMemo(()=>{ return { name } },[name]) return( {count} setCount(count+1)}>update count ) } 复制代码useMemo知识点合集useMemo 一看 就感觉跟到memo有种蜜汁关系,因为都有memo... 😄 1. 首先,memo 的用法是:函数组件里面的PureComponent 但是,如果函数组件被 Reacmo 包裹,且其实现中拥有 useState 或 useContext 的 Hook,当 context 发生变化时,它仍会重新渲染。 😄 2. 而且,memo是浅比较,意思是,对象只比较内存地址,只要你内存地址没变,管你对象里面的值千变万化都不会触发render 😄 3. 最后,useMemo 的作用是, 于是useMemo 作为一个有着暂存能力的,就来了: useCallback 为什么要使用useCallback?useMemo 解决了值的缓存的问题,那么函数呢? 下面这个🌰就是,当点击count的按钮,Effect组件render,遇到了: const onChange=(e)=>{ setText(e.target.value) } 复制代码则,重新生成了一个onChange函数,赋值给了Child组件,浅比较失败,Child组件成功重新render,尽管Child组件什么都没有做! const Child = memo(({data, onChange}) =>{ console.log('child render...') return ( child {data} ); }) const Hook =()=>{ console.log('Hook render...') const [count, setCount] = useState(0) const [name, setName] = useState('rose') const [text, setText] = useState('') const onChange=(e)=>{ setText(e.target.value) } return( count: {count} text : {text} setCount(count + 1)}>count + 1 ) } 复制代码如何使用useCallback? const onChange = useCallback((e)=>{ setText(e.target.value) },[]) 复制代码useCallback 知识点合集😄1.useMemo 与 useCallback 类似,都是有着缓存的作用。本质的区别可能就是: useMemo 是缓存值的 useCallback 是缓存函数的 😄2.没有依赖,添加空的依赖,就是空数组! useReducer 为什么要使用useReducer?顾名思义,useReducer就是 class 里面那个reducer 如何使用useReducer?举个🌰: const reducer =(state = 0, {type})=>{ switch (type) { case "add": return state+1 case 'delete': return state-1 default: return state; } } const Hook =()=>{ const [count, dispatch] = useReducer(reducer, 0) return( count:{count} dispatch({type:'add'})}>add dispatch({type:'delete'})}>delete ) } export default Hook 复制代码useReducer知识点合集暂无特别的...😼 useContext 为什么要使用useContext?useContext 就是 class 里面的 那个 context。 如何使用useContext? import React, {useContext, useReducer} from 'react' const reducer = (state = 0, {type}) => { switch (type) { case "add": return state + 1 case 'delete': return state - 1 default: return state; } } const Context = React.createContext(null); const Child = () => { const [count, dispatch] = useContext(Context) return ( child...{count} dispatch({type: 'add'})}>child add dispatch({type: 'delete'})}>child delete ) } const Hook = () => { const [count, dispatch] = useReducer(reducer, 10) return ( mom ... {count} dispatch({type: 'add'})}>mom add dispatch({type: 'delete'})}>mom delete ) } export default Hook 复制代码useContext知识点合集暂无特别的...😼 自定义hook!自定义一个当resize 的时候 监听window的width和height的hook import {useEffect, useState} from "react"; export const useWindowSize = () => { const [width, setWidth] = useState() const [height, setHeight] = useState() useEffect(() => { const {clientWidth, clientHeight} = document.documentElement setWidth(clientWidth) setHeight(clientHeight) }, []) useEffect(() => { const handleWindowSize = () =>{ const {clientWidth, clientHeight} = document.documentElement setWidth(clientWidth) setHeight(clientHeight) }; window.addEventListener('resize', handleWindowSize, false) return () => { window.removeEventListener('resize',handleWindowSize, false) } }) return [width, height] } 复制代码如何使用: const [width, height] = useWindowSize() 复制代码最后 |
CopyRight 2018-2019 实验室设备网 版权所有 |