react hook


hooks的目的是为了给函数式组件加上状态;
hooks 一律使用use作为前缀命名,常用钩子useState,useEffect,useContext(跨组件数据传递),useReducer(管理全局状态)useCallback(处理回调副作用),useRef(返回引用对象,不变)

1.useContext 跨组件传递数据

createContext useContext
一级组件创建:React.createContext
**index.tsx**
const defaultContextValue = {
  username: "阿莱克斯",
};
export const appContext = React.createContext(defaultContextValue);
** child.tsx**
二级三级消费:
import React, { useContext } from "react";
import { appContext } from "../index";
const value = useContext(appContext);
{value.username}

或者Provider,Consumer
一级组件创建:React.createContext
**index.tsx**
const defaultContextValue = {
  username: "阿莱克斯",
};
export const appContext = React.createContext(defaultContextValue);
<appContext.Provider value={ defaultContextValue }>
 <App />
</appContext.Provider>
** child.tsx**
二级三级消费:
import React, { useContext } from "react";
import { appContext } from "../index";
const value = useContext(appContext);
{value.username}
<appContext.Consumer>
 {(value) => {
        return <li>
        <p>{value.username}</p>
      </li>
}}
</appContext.Consumer>      

升级:全局context

新建appState.tsx. 导出AppStateProvider组件

appState.tsx

import React, { useState } from "react";

interface AppStateValue {
  username: string;
  shoppingCart: { items: { id: number; name: string }[] };
}

const defaultContextValue: AppStateValue = {
  username: "阿莱克斯",
  shoppingCart: { items: [] },
};

export const appContext = React.createContext(defaultContextValue);
export const appSetStateContext = React.createContext<
  React.Dispatch<React.SetStateAction<AppStateValue>> | undefined
>(undefined);
//最外层使用
export const AppStateProvider: React.FC = (props) => {
  const [state, setState] = useState(defaultContextValue);
  return (
  //相当于一个高阶的HOC
    <appContext.Provider value={state}>
      <appSetStateContext.Provider value={setState}>
        {props.children}
      </appSetStateContext.Provider>
    </appContext.Provider>
  );
};

index.tsc
最外层AppStateProvider包裹

import { AppStateProvider } from "./AppState";
ReactDOM.render(
  <React.StrictMode>
    <AppStateProvider>
      <App />
    </AppStateProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

二级组件消费

import React, { useContext } from "react";
import styles from "./Robot.module.css";
import { appContext, appSetStateContext } from "../AppState";

interface RobotProps {
  id: number;
  name: string;
  email: string;
}

const Robot: React.FC<RobotProps> = ({ id, name, email }) => {
  const value = useContext(appContext);
  const setState = useContext(appSetStateContext)
  const addToCart = () => {
    if(setState) { // 思考: 同学们可以想一想如何化简这里的代码
      setState(state => {
        return {
          ...state,
          shoppingCart: {
            items: [...state.shoppingCart.items, {id, name}]
          }
        }
      })
    }
  }
  return (
    <div className={styles.cardContainer}>
      <img alt="robot" src={`https://robohash.org/${id}`} />
      <h2>{name}</h2>
      <p>{email}</p>
      <p>作者:{value.username}</p>
      <button onClick={addToCart}>加入购物车</button>
    </div>
  );
};

export default Robot;

2.useEffect 副作用

1.与药物的副作用类似:减肥药(拉肚子),头孢(过敏);
2.纯函数
(1).给一个函数同样的参数,那么这个函数永远返回同样的
(2).函数式编程理念
3.副作用与纯函数相反,指一个函数处理了与返回值无关的事情;

y=f(x)纯函数
椭圆,一个x对应多个y,不确定的情况就是副作用;

副作用是坏事吗?
很多代码必须的借助副作用: AJAX,修改dom,甚至是console.log;
React:state状态的变化,生命周期,构建函数

3.useMemo

假设我们有一个计算函数,该函数需要大量时间才能得出结果,我们可以使用 useMemo 来缓存该函数的结果,以避免在每次渲染时都重新计算。

import { useMemo } from 'react';

function expensiveCalculation(number) {
  console.log('calculating...');
  let result = 0;
  for (let i = 0; i < number; i++) {
    result += i;
  }
  return result;
}

function App() {
  const [inputValue, setInputValue] = useState(0);
  
  const result = useMemo(() => expensiveCalculation(inputValue), [inputValue]);

  return (
    <div>
      <label>
        Input value:
        <input type="number" onChange={(e) => setInputValue(e.target.value)} />
      </label>
      <p>Result: {result}</p>
    </div>
  );
}

在这个例子中,我们定义了一个昂贵的计算函数 expensiveCalculation,然后在组件中使用 useMemo 来缓存其结果。每次 inputValue 更改时,useMemo 会检查依赖项数组 [inputValue] 是否更改,如果更改,它会重新计算 expensiveCalculation 的结果。否则,它将返回先前缓存的值。

自变量

{useState,useReducer,useContext}

因变量

{useMemo,useEffect,useCallback}

其他
useRef

import {useState} from ‘react’
function Count({data}){//data就相当于props
   return <i>{data}</i>
}
export default function App(){
   const [x,setX]=useState(0);
   const y=2*x+1;
   const changeX=()=>setX(x+1)const renderCountRef = useRef(1);
   const isOdd =renderCountRef.current%2!=0;
   renderCountRef.current++;
   //const changeX=useCallback(()=>setX(x+1),[x])
   return(<ul onClick={changeX}>
          <li>x是{x}</li>
          <li>y是{y}</li>
           <li>x是<Count data={x}/></li>
          <li>y是<Count data={y}/></li>
           {isOdd?<li>x是{x}</li>:null}//奇数次更新的时候显示
          
    </ul>)
    x变化y变化
}
1.自变量==>视图的变化
useState将X的值渲染为li标签的值,定义changX方法,将changX绑定为ul的点击回调函数
2.因变量==>视图 的变化
useMemo,useCallback在遇到性能瓶颈之前都可以不使用;
使用好处;y与changeX会缓存下来,只要x不变,读取的是缓存的值,
不使用时会基于x创建新的y与changX
3.副作用===>自变量导致因变量变化后,因变量不仅可以改变视图,还可以触发副作用
useEffect
请求数据,操作Dom
4.useReducer相当于进阶版的useState
多个state 吧x,y作为props传入
5.useContext
一级组件创建createContext之后,可以在后面任意二级,三级。。。直接使用useContext
6.useRef
自变量与因变量,因变量与视图,自变量与视图

其他

HOC higherOrde 高阶函数组件

1.返回了组件的函数;
2.通过组件嵌套的方法给子组件添加跟多功能
3.接收一个组件作为参数并返回一个经过改造的新组件
AddToCart.tsx

import React, { useContext } from "react";
import { appSetStateContext } from "../AppState";
import { RobotProps } from "./Robot";

export const withAddToCart = (ChildComponent: React.ComponentType<RobotProps>) => {
    return (props) => { 
        const setState = useContext(appSetStateContext)
        const addToCart = (id, name) => {
            if (setState) {
            // 思考: 同学们可以想一想如何化简这里的代码
            setState((state) => {
                return {
                ...state,
                shoppingCart: {
                    items: [...state.shoppingCart.items, { id, name }],
                },
                };
            });
            }
        }
        return <ChildComponent {...props} addToCart={addToCart} />
    };
}

Robot.tsx
消费useContext

import React, { useContext } from "react";
import styles from "./Robot.module.css";
import { appContext, appSetStateContext } from "../AppState";
import { withAddToCart } from './AddToCart';
export interface RobotProps {
  id: number;
  name: string;
  email: string;
  addToCart: (id, name) => void;
}

const Robot: React.FC<RobotProps> = ({ id, name, email, addToCart }) => {
  const value = useContext(appContext);
  return (
    <div className={styles.cardContainer}>
      <img alt="robot" src={`https://robohash.org/${id}`} />
      <h2>{name}</h2>
      <p>{email}</p>
      <p>作者:{value.username}</p>
      <button onClick={() => addToCart(id, name)}>加入购物车</button>
    </div>
  );
};
export default withAddToCart(Robot);

appState.tsx
导出AppStateProvider组件 创建

import React, { useState } from 'react'

interface AppStateValue {
    username: string;
    shoppingCart: { items: { id: number; name: string }[] };
}


const defaultContextValue: AppStateValue = {
    username: "阿莱克斯",
    shoppingCart: { items: [] },
};
export const appContext = React.createContext(defaultContextValue);
export const appSetStateContext = React.createContext<
    React.Dispatch<React.SetStateAction<AppStateValue>> | undefined
>(undefined);

export const AppStateProvider: React.FC = (props) => {
    const [state, setState] = useState(defaultContextValue);
    return (
        <appContext.Provider value={state}>
            <appSetStateContext.Provider value={setState}>
                {props.children}
            </appSetStateContext.Provider>
        </appContext.Provider>
    );
}

自定义hook use***

**addToCart.tsx***
export const useAddToCart = () => {
    const setState = useContext(appSetStateContext)
    const addToCart = (id, name) => {
        if (setState) {
        // 思考: 同学们可以想一想如何化简这里的代码
        setState((state) => {
            return {
            ...state,
            shoppingCart: {
                items: [...state.shoppingCart.items, { id, name }],
            },
            };
        });
        }
    }
    return addToCart;
}

***RobotDiscount.tsx**
import { useAddToCart } from "./AddToCart";
interface RobotProps {
  id: number;
  name: string;
  email: string;
}

const RobotDiscount: React.FC<RobotProps> = ({ id, name, email }) => {
  const value = useContext(appContext);
  const addToCart = useAddToCart();
  return (
    <div className={styles.cardContainer}>
      <img alt="robot" src={`https://robohash.org/${id}`} />
      <h2>打折商品</h2>
      <h2>{name}</h2>
      <p>{email}</p>
      <p>作者:{value.username}</p>
      <button onClick={() => addToCart(id, name)}>加入购物车</button>
    </div>
  );
};
export default RobotDiscount;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值