尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

React-Hooks笔记

React-Hooks笔记 class组件存在的问题和添加Hooks的原因一、函数组件的特点没有组件实例没有生命周期没有state和setState只能接收props二、class组件的问题大型组件很难拆分和重构很难测试即class不易拆分相同业务逻辑分散到各个方法中逻辑混乱复用逻辑变得复杂如MixinsHOCRender Prop三、React组件更易用函数表达React提倡函数式编程函数更灵活更易拆分更易测试但是函数组件太简单需要增强能力-----HooksHooks的具体讲解1、State Hook注意让函数组件实现state和setState默认函数组件没有state函数组件是一个纯函数执行完即销毁无法存储state需要State Hook 即把state功能 “钩” 到纯函数中1、函数组件import React from react import { useState } from react; function ClickCount() { const [count, setCount] useState(0); return ( div p你点击了{count}次/p button onClick{() setCount(count 1)}点击/button /div ) } export default ClickCount;2、class组件import React from react class ClickCountClass extends React.Component { constructor(props) { super(props); this.state { count: 0 } this.handleClick this.handleClick.bind(this); } render() { return div p你点击了{this.state.count}次/p button onClick{this.handleClick}点击/button /div } handleClick() { this.setState({ count: this.state.count 1 }) } } export default ClickCountClass;3、useState使用总结useState(0)传入初始值返回数组[state,setSate]通过state获取值通过setState(1)修改值4、Hooks命名规范规定所有Hooks都用use开头如useXXX自定义Hooks也要用use开头非Hooks的地方尽量不要用useXXX写法Effect Hook具体讲解1、让函数组件模拟生命周期默认函数组件没有生命周期函数组件是一个纯函数执行完即销毁自己无法实现生命周期使用Effect Hook把生命周期“钩”到纯函数中2、模拟class组件的DidMount和DidUpdatauseEffect(() { console.log(name, name); });3、模拟class组件的DidMountuseEffect(() { console.log(组件挂载); }, []);4、模拟class组件的DidUpdatauseEffect(() { console.log(count, count, name, name); }, [count, name]);注意只有写在【】中间的元素变化更新了才会触发DidUpdata如果元素没有写在这里那么就算元素改变了也不会触发DidUpdata5、useEffect总结模拟DidMount --- useEffect依赖[]模拟DidUpdata --- useEffect无依赖或者依赖 [a, b]模拟WillUnMount --- useEffect 中返回一个函数6、useEffect让纯函数有了副作用默认情况下执行纯函数输入参数返回结果无副作用所谓副作用就是对函数之外造成影响如设置全局定时任务而组件需要副作用所以需要useEffect “钩” 入纯函数中注意useEffect可能会出现内存泄漏的问题比如纯函数的Effect中写了定时任务没有做销毁而外部又将纯函数销毁了那么定时器不会自动关闭还会继续存在。useRef具体讲解注意:主要用于获取Dom节点通过.current调用import React, { useRef, useEffect } from react; function UseFef() { const inputRef useRef(null); useEffect((){ console.log(inputRef.current);//Dom节点 },[]) return ( div ref{inputRef} 按钮 /div ); } export default UseFef;useContext具体讲解注意React中的Context具体意义就是全局存值。可以理解为vuex或者Rudex的简单版本import React, { useContext } from react; //主题颜色 const Themes { light: { foreground: #000, background: #fff }, dark: { foreground: #fff, background: #222 } } const ThemeContext React.createContext(Themes.light); function ThemedButton() {//底层组件 const theme useContext(ThemeContext);//使用useContext获取主题颜色 return ( button style{{ background: theme.background, color: theme.foreground }}你好/button ) } function Toolbar() {//中间组件 return ( ThemedButton / ) } function App() {//顶层组件 return ( ThemeContext.Provider value{Themes.dark}//使用ThemeContext.Provider提供主题颜色 Toolbar / /ThemeContext.Provider ) } export default App;useReducer具体讲解import React, { useReducer } from react; const initialState { count: 0 }; const reducer (state: any, action: any) { switch (action.type) { case increment: return { count: state.count 1 }; case decrement: return { count: state.count - 1 }; default: return state; } } function App() { //很像useStateconst [count, setCount] useState(0); const [state, dispatch] useReducer(reducer, initialState); return ( div pCount: {state.count}/p button onClick{() dispatch({ type: increment })}Increment/button button onClick{() dispatch({ type: decrement })}Decrement/button /div ) } export default App;1、useReducer和redux的区别useReducer是useState的代替方案用于state的复杂变化useReducer是单个组件的状态管理组件通讯还是需要propsredux是全局的状态管理多组件共享数据useMemo的具体讲解注意用于Hooks性能优化的1、有问题的情况注意我只改变父组件的数据情况下子组件会跟着一起发生改变去进行更新渲染。这样的情况是不应该的因为我子组件没有数据变化不应该让他重新渲染这样会造成资源的浪费耗费性能。import React, { useMemo, useState } from react; //子组件 function Child({ userInfo }) { console.log(Child组件渲染); return ( div pName: {userInfo.name}/p pAge: {userInfo.age}/p /div ) } //父组件 function App() { console.log(父组件渲染); const [count, setCount] useState(0); const [name, setName] useState(江停); const userInfo {name, age: 30}; return ( div Child userInfo{userInfo} / button onClick{() setCount(count 1)}Count: {count}/button button onClick{() setName(name 1)}Name: {name}/button /div ) } export default App;2、memo的应用注意虽然上述情况react会自己做nodeChild的校验如果在没有影响性能的情况下可以不用做memo的性能优化操作注意类似于PureComponent,对props进行浅层的比较注意用useMemo缓存数据当name变化时userInfoMemo会重新计算[]表示依赖项当依赖项变化时useMemo会重新计算import React, { memo, useMemo, useState } from react; //子组件 const Child memo(({ userInfo }: { userInfo: { name: string; age: number } }) { console.log(Child组件渲染); return ( div pName: {userInfo.name}/p pAge: {userInfo.age}/p /div ) }) //父组件 function App() { console.log(父组件渲染); const [count, setCount] useState(0); const [name, setName] useState(江停); const userInfo {name, age: 30}; //用useMemo缓存数据当name变化时userInfoMemo会重新计算[]表示依赖项当依赖项变化时useMemo会重新计算 const userInfoMemo useMemo(() userInfo, [name]); return ( div Child userInfo{userInfoMemo} / button onClick{() setCount(count 1)}Count: {count}/button button onClick{() setName(name 1)}Name: {name}/button /div ) } export default App;3、useMemo总结React默认会更新所有子组件class组件使用SUC和PureComponent做优化Hooks中使用useMemo但是优化的原理都是一样的useCallback的具体讲解1、有问题的情况注意当我们在子组件内添加一个传递的函数之前的子组件又会自动更新。import React, { memo, useMemo, useState } from react; //子组件 const Child memo(({ userInfo,onChange }: { userInfo: { name: string; age: number }, onChange: () void }) { console.log(Child组件渲染); return ( div pName: {userInfo.name}/p pAge: {userInfo.age}/p button onClick{onChange}Change/button /div ) }) //父组件 function App() { console.log(父组件渲染); const [count, setCount] useState(0); const [name, setName] useState(江停); const userInfo {name, age: 30}; //用useMemo缓存数据当name变化时userInfoMemo会重新计算[]表示依赖项当依赖项变化时useMemo会重新计算 const userInfoMemo useMemo(() userInfo, [name]); const onChange (e: React.ChangeEventHTMLInputElement) { console.log(onChange,e.target.value); } return ( div Child userInfo{userInfoMemo} onChange{(e: React.ChangeEventHTMLInputElement) onChange(e)} / button onClick{() setCount(count 1)}Count: {count}/button button onClick{() setName(name 1)}Name: {name}/button /div ) } export default App;2、useCallback的封装import React, { memo, useMemo, useState, useCallback } from react; //子组件 const Child memo(({ userInfo,onChange }: { userInfo: { name: string; age: number }, onChange: (e: any) void }) { console.log(Child组件渲染); return ( div pName: {userInfo.name}/p pAge: {userInfo.age}/p button onClick{onChange}Change/button /div ) }) //父组件 function App() { console.log(父组件渲染); const [count, setCount] useState(0); const [name, setName] useState(江停); const userInfo {name, age: 30}; //用useMemo缓存数据当name变化时userInfoMemo会重新计算[]表示依赖项当依赖项变化时useMemo会重新计算 const userInfoMemo useMemo(() userInfo, [name]); const onChange useCallback((e) { console.log(onChange,e.target.value); }, []); return ( div Child userInfo{userInfoMemo} onChange{onChange} / button onClick{() setCount(count 1)}Count: {count}/button button onClick{() setName(name 1)}Name: {name}/button /div ) } export default App;3、useCallback的总结useMemo缓存数据useCallback缓存函数但是传递的函数不要写成箭头函数这样可能后导致useCallback失效两者都是React Hooks的常见优化策略
返回列表