React笔记(七)

2024 年 5 月 3 日 星期五(已编辑)
/
7
摘要
这篇文章介绍了React中常用的Hooks和一些相关概念,包括useReducer、useMemo、React.memo、useCallback、React.forwardRef、useImperativeHandle、Class组件、生命周期函数、组件通信、zustand等内容。每个部分都有相应的代码示例和解释。
这篇文章上次修改于 2024 年 5 月 7 日 星期二,可能部分内容已经不适用,如有疑问可询问作者。

阅读此文章之前,你可能需要首先阅读以下的文章才能更好的理解上下文。

1.useReducer

和useState作用类似,用于管理相对复杂的状态数据

//1.定义一个reducer函数(根据不同的action返回不同的状态)
function reducer(state,action) {
    switch(action.type){
            casse 'INC':
                return state+1
            case 'DEC':
                return state-1
            default:
                return state
    }
}
//2.在组件中调用useReducer,并传入reducer函数和状态初始值
const [state,dispatch] = useReducer(reducer,0)
//3.通过dispatch传入一个action对象
dispatch({
    type: 'INC'
})
//分派action时传参
dispatch({
    type: 'SET',
    payload: 100
})

function reducer (state, action){
    switch(action.type){
        case 'INC':
            return state+1
        case 'DEC':
            return state-1
        case 'SET':
            return action.payload
        default: 
            return state
    }
}

2.useMemo

在组件每次重新渲染的时候缓存计算的结果,缓存消耗非常大时候使用

useMemo(() => {
    //根据count返回计算的结果
},[count])

3.React.memo

允许组件在Props没有改变的情况下跳过渲染,React组件默认父组件重新渲染时候,子组件也会随之重新渲染

//只有在Props改变时候才会重新渲染
const MemoComponet = memo(function SomeComponent(props){
    //...子组件内容
})

4.React.memo-props的比较机制

在memo缓存组件之前,React会对每一个prop使用Object.is比较新值和老值,返回true,表示没有变化

//prop是简单类型
Object.is(3,3) => true (没有变化)
//prop是引用类型 (对象/数组)
Object([],[]) => false (有变化,React只关心引用是否改变)
//保证引用稳定 -- useMemo
const list = useMemo(() => {
    return [1,2,3]
},[])

5.useCallback

作用:在组件多次渲染时候缓存函数(引用类型),使用useCallback包裹函数以后跨域保证重新渲染时候保持稳定

const Input = meme(function Input ({ onChange }) {
    console.log('子组件重新渲染')
    return <input type='text' onChange={(e) => onChange(e.target.value)}></input>
})

function App(){
    //传给子组件的函数
    const changeHandler = useCallback((value) => console.log(value),[])
    const [count,setCount] = useState(0)
    return (
        <div>
            {/*把函数作为prop传给子组件*/}
            <Input onChange={changeHandler} />
            <button onClick={() => setCount(count+1)}>
            {count}
            </button>
        </div>
    )
}

6.React.forwardRef

父组件通过ref获取子组件内部的input元素使其聚焦

//子组件
const Input = forwardRef((props,ref) => {
    return <input type='text' ref={ref}/>
})

//父组件
function App() {
    const inputRef = useRef(null)
    return (
        <div>
            <Input ref={inputRef}/>
        </div>
    )
}

7.useInperativeHandle

父组件通过ref调用子组件内部的focus方法实现聚焦

//子组件
const Input = forwadRef((props,ref) => {
    const inputRef = useRef(null)
    //实现聚焦路径函数
    const foucuHandler = () => {
        inputRef.current.foucs()
    }
    //暴露函数给父组件
    useImperativeHandle(ref,() => {
        return {
            foucsHandler
        }
    })
    return <input type='text' ref={inputRef}/>
}
                        
//父组件
function App() {
    const sonRef = useRef(null)
    const foucsHand;er = () => {
        sonRef.current.foucsHandler()
    }
    return (
        <div>
            <Input ref={inputRef}/>
            <button onClick={foucsHandler}>foucs</button>
        </div>
    )
}

8.Class类组件(Class API)

通过JS中的类来组织代码,老版本项目中喜欢用,现在已经不推荐

//1.通过类属性state定义状态数据
//2.通过setState方法修改数据
//3.如果render来写UI模板(JSX)
class Counter extends Component {
    //定义状态变量
    state = {
        count: 0
    }
    
    //事件回调
    clickHandler = () => {
        this.setState({
            count: this.state.count + 1
        })
        
    //事件回调(JSX)
    render () {
         return <button onClick={this.clickHandler}>{this.state.count}</button>   
    }
}

9.类组件生命周期函数

组件从创建到销毁的各个阶段自动执行的函数

//1.componentDidMount:组件挂载完毕自动执行 -异步数据获取
//2.componentWillUnmount:组件卸载时自动执行--清理副作用

10.类组件通信

//1.父传子:通过prop绑定数据
class Son extends Componet {
    render() {
        return <div>我是子组件{this.props.msg}</div>
    }
}

class Parent extends Component {
    state = {
        msg: 'this is parent msg'
    }
    render() {
        return <div>我是父组件<Son msg={this.state.msg}/></div>
    }
}
//2.子传父:通过prop绑定父组件的函数,子组件调用
class Son extends Componet {
    render() {
        return <div>我是子组件{this.props.msg}</div>
        <button onClick={()=>this.props.onGetSonMsg('this is son msg')}></button>
    }
}

class Parent extends Component {
    state = {
        msg: 'this is parent msg'
    }
    
    getSonMsg = (sonMsg) => {
        console.log(sonMsg)
    }
    
    render() {
        return <div>我是父组件<Son msg={this.state.msg}  onGetSonMsg={this.getSonMsg}/></div>
    }
}
//3.兄弟通信:状态提升,通过父组件桥接

11.zustand

状态管理工具类似于Redux

//1.创建store
//2.函数参数必须返回一个对象,对象内部编写状态数据和方法
//3.set是用来修改数据的专门方法必须调用它来修改函数
//语法1:参数是函数 需要用到原来的数据计算
//语法2:参数是对象set({count:100})
import { create } from 'zustand'

const store = create((set) => {
    return {
        //状态数据
        count: 0,
        //修改状态数据的方法
        inc: () -> {
            set((state) => ({count: state.count + 1}))
        }
    }
})

...
const [count, inc] = store()

zustand-异步支持

const Store = create((set) => {
    return {
        //状态数据
        channeList: [],
        //异步方法
        fetchGetList: async () => {
            const res = await fetch(URL)
            const jsonData = await res.json()
            //调用set方法更新状态
            set({
                channelList: jsonData.data.channalist
            })
        }
    }
})
...
const { channeList,fetchGetList } = Store()

zustand-切片模式,,当单个store比较大的时候,跨域采用切片模式进行模块拆分组合

//组合切片
const useStore = create((...a) => {
    ...Store(...a),
    ...store(...a)
})
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...