React Hooks 组件化开发(常用)

本文章视频地址:视频链接

一、React组件分类

在这里插入图片描述

二、Hook函数概览

Hook 是 React 16.8 的新增特性!并且只能运用到函数组件中!
在这里插入图片描述

1.useState

作用:在函数组件中使用状态,修改状态值可让函数组件更新,类似于类组件中的setState
语法: const [state,setState] = useState(initialState); 返回一个 state,以及更新 state 的函数

import React, { useState } from "react";
export default function Demo(props) {
    let [num, setNum] = useState(10);
    const handler = () => {
        setNum(num + 1);
    };
    return <div>
        <span>{num}</span>
        <button onClick={handler}>新增</button>
    </div>;
};

2.useEffect

作用:在函数组件中使用生命周期函数
语法:具备很多情况 useEffect([callback],[dependencies])

import React, { useState, useEffect } from "react";
export default function Demo() {
    let [num, setNum] = useState(10),
        [x, setX] = useState(100);

    /* 
     在组件 第一次渲染完 && 每一次更新完 调用 
     等同于 componentDidMount && componentDidUpdate
    */
    useEffect(() => {
        console.log('@1', num, x);
    });

    /* 
     只在组件 第一次渲染完 调用 
     等同于 componentDidMount
    */
    useEffect(() => {
        console.log('@2', num, x);
    }, []);

    /* 
     第一次渲染完 以及 依赖的状态发生改变 时调用
    */
    useEffect(() => {
        console.log('@3', num);
    }, [num]);

    /* 
     返回的函数将在 组件卸载后 被调用
     等同于 componentWillUnmount
     */
    useEffect(() => {
        return () => {
            console.log('@4');
        };
    }, []);

    return <div>
        <span>{num}</span>
        <button onClick={() => { setNum(num + 1); }}>处理</button>
        <br />
        <span>{x}</span>
        <button onClick={() => { setX(x + 1); }}>处理</button>
    </div>;
};

【注意点1:】只能在函数最外层调用 Hook,不要在循环、条件判断或者子函数中调用。

import React, { useState, useEffect } from "react";
export default function Demo() {
    let [num, setNum] = useState(10);
    if (num >= 10) {
        // Error:React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render  react-hooks/rules-of-hooks
        useEffect(() => {
            console.log('@1', num);
        });
    }
    return <div>
        <span>{num}</span>
        <button onClick={() => { setNum(num + 1); }}>处理</button>
    </div>;
};

【注意点2:】异步获取数据

不能直接对[callback]设置async,因为它只能返回一个函数(或者不设置返回值)

import React, { useState, useEffect } from "react";
const queryData = () => {
    return fetch('/api/subscriptions/recommended_collections')
        .then(response => {
            return response.json();
        });
};
export default function Demo() {
    let [data, setData] = useState([]);
    /* // Warning: useEffect must not return anything besides a function, which is used for clean-up.
    useEffect(async () => {
        let result = await queryData();
        setData(result);
        console.log(result);
    }, []); */
    useEffect(() => {
        const next = async () => {
            let result = await queryData();
            setData(result);
            console.log(result);
        };
        next();
    }, []);
    return <div>
        ...
    </div>;
};

3.useRef

在这里插入图片描述
简单来说,useRef就像一个储物箱,你可以随意存放任何东西,再次渲染时它会去储物箱找,createRef每次渲染都会返回一个新的引用,而useRef每次都会返回相同的引用。

import React, { useState, useEffect, useRef, createRef } from "react";
let prev;
export default function Demo() {
    const [num, setNum] = useState(0);
    const btnBox = useRef(null); //换成createRef也是可以的
    if (!prev) {
        prev = btnBox;
    } else {
        console.log(prev === btnBox);
    }
    useEffect(() => {
        console.log(btnBox.current);
    }, []);
    return <div>
        <span>{num}</span>
        <button ref={btnBox} onClick={() => setNum(num + 1)}>按钮</button>
    </div>;
};

4.useContext

作用:跨组件共享数据
说明:在没有hook之前,我们通常都会通过 xxxContext.Provider 和 xxxContext.Consumer 的方式来传递和获取context的值,使用hook之后,传递context的方式不变,但子元素获取context的方式变得更加的简洁。

// 以前的定义方式
const CountContext = React.createContext()
 <CountContext.Provider value={{ count: 10 }}>
     <...自定义的组件>
 </CountContext.Provider>
// 子元素
<CountContext.Consumer>
    { value => { console.log(value.count) }} //10
</CountContext.Consumer>


//使用context的获取方式
const countObj = useContext(CountContext)
console.log(countObj.count) // 10

5.useReducer

作用:useReducer相当于是useState的升级版,与useState类似,都是用来保存状态,但它的不同点在于可以定义一个reducer的纯函数,来处理复杂数据。

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

6.useCallback

作用:函数式组件中,每一次更新状态,自定义的函数都要进行重新的声明和定义,如果函数作为props传递给子组件,会造成子组件不必要的重新渲染,有时候子组件并没有使用到父组件发生变化的状态,此时可以使用useCallback来进行性能优化,它会为函数返回一个记忆的值,如果依赖的状态没有发生变化,那么则不会重新创建该函数,也就不会造成子组件不必要的重新渲染。

父组件:

import React, { useState, useCallback } from "react";
import Child1 from './Child1';
import Child2 from './Child2';
export default function App() {
    let [val, setVal] = useState('');
    let [name, setName] = useState('张三');

    const handler1 = useCallback(() => {
        setVal('哈哈哈');
    },[val]);

    const handler2 = useCallback(() => {
        setName('李四');
    }, [name]);
    
    return <div>
        <input type="text" value={val}
            onChange={ev => {
                setVal(ev.target.value);
            }} />
        <Child1 handler={handler1} />
        <Child2 handler={handler2} />
    </div>;
};

子组件Child1:

【注】:如果子组件是类组件,则可以使用shouldComponentUpdate或者PureComponent 做优化

import React from "react";
export default class Child1 extends React.PureComponent {
    render() {
        console.log('child1 render');
        return <div>
            <button onClick={this.props.handler}>处理1</button>
        </div>;
    }
}

子组件Child2:

【注】:如果子组件是函数组件,则需要useCallback和memo配合使用

import React, { memo } from "react";
const Child2 = memo(function Child2({ handler }) {
    console.log('child2 render');
    return <div>
        <button onClick={handler}>处理2</button>
    </div>;
});
export default Child2;

7.useMemo

  • 作用:useMemo也是返回一个记忆的值,如果依赖的内容没有发生改变的话,组件也不会重新渲染。
  • 注意:useMemo与useCallback的不同点在于useMemo需要在传入的函数里需要return 一个值。

父组件:

import { useState, useMemo } from 'react'
import Test from './Test';
function App() {
  console.log('App render');
  const [count, setCount] = useState(0);
  const [name, setName] = useState('张三');
  function changeName(name) {
    return name + '---名字改变了';
  }
  const Name = useMemo(() => changeName(name), [name]);
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => { setCount(count + 1) }}>计数</button>
      <button onClick={() => { setName(name + '666') }}>名字</button>
      <Test Name={Name}></Test>
    </div>
  )
}

export default App


子组件:

import { memo } from "react";
const Test = memo(({ Name }) => {
    console.log('Test render');
    return <div>
        <div>{Name}</div>
    </div>;
})
export default Test;

总结:useCallback缓存函数,useMemo缓存数据。

8.自定义Hook

使用自定义hook可以将某些组件逻辑提取到可重用的函数中

import React, { useState } from "react";
const usePartState = function usePartState(initial) {
    let [state, setState] = useState(initial);
    const setPartState = (partState) => {
        setState({
            ...state,
            ...partState
        });
    };
    return [state, setPartState];
};
export default function Demo() {
    let [state, setState] = usePartState({
        x: 10,
        y: 20
    });
    return <div>
        <span>{state.x}</span>
          
        <span>{state.y}</span>
        <button onClick={() => {
            setState({
                x: state.x + 1
            });
        }}>处理x</button>
    </div>;
};

注意:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React HooksReact 16.8版本引入的一种新特性,它可以让你在函数组件中使用状态(state)和其他React特性,而无需编写类组件。通过Hooks,你可以在无需修改组件结构的情况下,复用状态逻辑,并且使组件更加简洁和易于理解。 Hooks提供了一系列的钩子函数,最常用的是useState()和useEffect()。useState()可以在函数组件中声明和使用状态,并且可以通过函数调用来更新状态。例如,你可以使用useState()来创建一个计数器: ``` import React, { useState } from 'react'; const Counter = () => { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } ``` 在上面的例子中,useState(0)初始了一个名为count的状态变量,并将其初始值设置为0。setCount是一个用于更新count的函数。每次点击按钮时,我们通过调用setCount来更新count的值。 另一个常用的钩子函数是useEffect(),它用于处理副作用操作,比如订阅数据、网络请求或者手动修改DOM。useEffect()接受两个参数:一个回调函数和一个依赖数组。回调函数将在组件渲染时执行,并且可以返回一个清理函数。依赖数组用于定义在依赖项改变时是否重新运行回调函数。 这只是React Hooks的简单介绍,还有其他很多有用的Hooks,比如useContext()、useReducer()等。Hooks提供了一种更加灵活和直观的方式来管理组件状态和副作用,使得函数组件的编写更加简单和可维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值