03-react基础知识-HOOK

一、useState

二、 useEffect

三、 useCallback

四、 useMemo 

五、 useContext

        含义:useContex用于在组件中获取上层组件通过 Context 提供的数据。它可以让你跨越组件树层级来访问共享的数据,避免了通过层层传递 props 的带来的问题。

1.实现数据的跨级传递(父组件的数据可以直接传递给孙组件或者孙孙组件)

2.组件本身可以充当数据的消费者和数据的提供者

3.若要在子组件中使用父组件的过程中,修改了子组件中的数据后,父组件中使用了该变量的地方都会刷新,则在使用provider和value进行传值时,可以以数组的形式进行传递,这样子组件即可正常使用set来修改数据了(同步更新)


                
            
//app上下文对象==================================================
// 1-1:=======创建appctx文件并编辑下面语句
import React from "react";
// 创建一个上下文对象
let Appctx = React.createContext({})
// 导出appctx对象
export default Appctx


//子组件的上下文对象==========================================================
import React from "react";
// 创建一个上下文对象
let Sonctx = React.createContext({})
// 导出Sonctx对象
export default Sonctx

//孙组件上下文对象==========================================================
import React from "react";
// 创建一个上下文对象
let GrandsonCtx = React.createContext({})
// 导出GrandsonCtx对象
export default GrandsonCtx



//app组件中=============================================================
import React, { useState, useCallback } from 'react'
import Son from './component/hook/01-Son.jsx'
//1-2======== 引入自己创建的Appctx上下文对象
import Appctx from './component/hook/01-app.jsx'
function App() {
  // 定义一个appmsg数据
  let [appmsg, setmsg] = useState({ name: "jack", age: 23 })
  return (
    
app组件
{appmsg.name}
{/* 1-3=======:使用provider标签和value属性来传递 父组件的appmsg数据*/}
) } export default App //son组件中=================================================================================== import React, { useContext, useState } from 'react' import Grandson from './02-granSon.jsx' //1-5======: 引入appctx上下文对象 import Appctx from './01-app.jsx' // 2-1:引入Sonctx这个上下文对象,是自己创建的 import Sonctx from './01-Sonctx.jsx' function Son() { // 1-6======:引入useContext这个函数,用useContext来接收从父组件传递过来的数据进行解构赋值 let obj = useContext(Appctx) console.log("son组件的obj222", obj); //2-2: son组件可以是消费者,也可以作为别人的数据提供者:定义一个变量sonmsg const [sonmsg, setsonmsg] = useState({ name: "小将", age: 26, sex: "girl" }) return (
son组件
{/* 这里即可正常使用父组件传递过来的数据 */}
{obj.name}
{obj.age}
son组件的值==当孙组件进行修改了sge数据,这里是否会改变======{sonmsg.age}
{/* 使用provider标签和value属性进行传递 */} {/*2-3: son组件给grandson组件提供数据 */} {/* 这里将son的数据sonmsg和setsonmsg传递给了孙组件,即可实现在孙组件中修改子组件的值了 */}
) } export default Son //孙组件中================================================================ import React, { useContext } from 'react' import Appctx from './01-app' // 2-4====引入Sonctx这个上下文对象 import Sonctx from './01-Sonctx' function Grandson() { // 2-5===使用usecontext来接收从son组件中传递过来的数据进行解构赋值 let [granobj, setsonmsg] = useContext(Sonctx) console.log("grandson的数据::孙组件", granobj, 1111, setsonmsg); // 父组件可以直接将其数据传递给孙组件乃至孙孙组件 let Apobj = useContext(Appctx) console.log("app传递过来的数据", Apobj); let change = () => { // 这是主流的写法,19行为深拷贝的概念,这不是标准的写法 granobj.age = "33" setsonmsg(JSON.parse(JSON.stringify(granobj))) } return (
Grandson组件
{/* 2-6===即可将其看作变量正常使用 */}
{granobj.name}
{granobj.age}
{granobj.sex}
) } export default Grandson

六、useReduce 

含义:和useState类似,都是用来管理组件状态的,只是useReducer返回的dispatch函数是用来改变state的action值得,而不是直接设置state的值,不同的action如何产生新的state的值是在reducer函数里面定义的。

        格式:const [state,dispatch]=usereducer(reducer,initialArg,init?)

state:当前的变量

dispatch:用于修改state的函数,类似于usestate中的set函数

reducer:一个函数,格式为:let reducer=(currentState,action)=>newState,该函数会接收当前的state和当前的dispatch中的action为参数,然后返回一个state,也就是说,reducer函数负责状态转换的工作。(可以决定如何修改state这个变量

通过当前的状态(state)和动作(action)返回修改后的新的状态的值,接收两个参数:状态值(state)和状态值(action

initialArg:state的初始值

init:把第二个参数传给了第三个函数,让这个函数处理一下,处理的结果作为初始值传递给state

import React, { useReducer } from 'react'

function App() {
  let [count, setcount] = useReducer((currentstate, action) => {
    console.log(currentstate, action);
    // count的值是return返回的值,返回为20的话,点击按钮,页面的变量为20咯,再一次点击:当前的值也就是return返回的值20,页面也就不会再刷新了
    return 20
    // 返回为action的话,传递的是最新的值,点击按钮,页面便是修改后的值:1,6,11。。。。。。。。
    // return action
    //若有第三个参数存在的话就是将第二个参数处理一下,然后将处理过的数据给state作为初始值:这里是将1交给第三个参数将其加100后给count。最后页面一加载,页面显示的是101
  }, 1, (arg) => { return arg + 100 })
  let change = () => {
    setcount(count + 5)
  }
  return (
    
app组件
{count}
) } export default App

进阶版

若该变量里面的数据比较多,对其进行修改和传递的写法

问:1.switch里面的case语句都是相似的,但为什么不直接使用下面这个写法呢

                

        上面的写法是处理好了再将处理好了再传递过去修改

下面的写法:在case里面可以写业务逻辑的,可以自己决定如何处理该数据,也就是统一来配置修改仓库的逻辑

case语句里面的修改是统一修改的逻辑代码。

2.case语句里的为什么要大写呢?

答:为了和普通的数据进行区分,不是数据,是取数据和保存数据的一个判断。

import React, { useReducer } from 'react'

function App() {
  // 1.1====让count的初始值为obj这个对象
  let obj = { name: "cup杯子", price: "14", comment: "非常好呀,下次还来" }
  // 1.2解构赋值====这里的dispatch相当于usestate的set函数
  let [count, dispatch] = useReducer(reducer, obj)

  // 1.3=========定义reducer函数:currentstate:为当前的那个状态,action传进来的最新的那个
  let reducer = (currentstate, action) => {
    console.log("当前的那个状态:", currentstate, "传进来的那个状态:", action);
    // 1.5==== 用switch进行判断,匹配是否匹配
    switch (action.type) {
      case "NAME":
        // 1.6===将新值传递给旧值:currentstate为旧值,action为新值
        currentstate.name = action.value
        break;
      case "PRICE":
        currentstate.price = action.value
        break;
      case "COMMENT":
        currentstate.comment = action.value
        break;
    }
    //1.7===== currentstate确实被修改了,但它本身是一个引用数据,属性值改变了,但属性没改,返回的还是引用数据所以页面不会刷新,需要用到深拷贝的知识点

    return JSON.parse(JSON.stringify(currentstate))
  }


  // 1.4====:通过dispatch中的type和value来实现数据修改
  let change = () => {
    dispatch({ type: "PRICE", value: "20" })
  }
  return (
    
app组件
{count.name}
{count.price}
) } export default App

进阶版,将reducer函数封装到一个文件中,直接引进来使用。

将reducer封装到一个文件中,引入使用=========================================================
import { useReducer } from "react";
function usestore() {
    // 1.1====让count的初始值为obj这个对象
    let obj = { name: "cup杯子", price: "14", comment: "非常好呀,下次还来" }

    // 1.3=========定义reducer函数:currentstate:为当前的那个状态,action传进来的最新的那个
    let reducer = (currentstate, action) => {
        console.log("当前的那个状态:", currentstate, "传进来的那个状态:", action);
        // 1.5==== 用switch进行判断,匹配是否匹配
        switch (action.type) {
            case "NAME":
                // 1.6===将新值传递给旧值:currentstate为旧值,action为新值
                currentstate.name = action.value
                break;
            case "PRICE":
                currentstate.price = action.value
                break;
            case "COMMENT":
                currentstate.comment = action.value
                break;
        }
        //1.7===== currentstate确实被修改了,但它本身是一个引用数据,属性值改变了,但属性没改,返回的还是引用数据所以页面不会刷新,需要用到深拷贝的知识点

        return JSON.parse(JSON.stringify(currentstate))
    }
    // 解构赋值:将store的初始值赋值为obj这个对象
    let [store, dispatch] = useReducer(reducer, obj)
    return [store, dispatch]
}
// 导出的是自己自定义的hook
export default usestore

app组件中===================================================

import React, { useReducer } from 'react'
import Son from './component/01-son.jsx'
// 引入自己定义的storehook
import usestore from './store.jsx'
function App() {
  // 使用自定义的
  let [store, dispatch] = usestore()
  console.log(store);
  // 使用action将name的值改为海绵宝宝好杯子
  let action = { type: "NAME", value: "海绵宝宝好杯子" }
  // 点击按钮,则调用dispatch函数,
  let change = () => {
    dispatch(action)
  }

  // 现在存在一个问:app组件和son组件中都有name属性,在son组件中点击按钮将name的值改变了,son页面的值改变了,但app组件没有改变
  // 因为引进来的是一个函数,每一次调用的都是独立的结果,各各自是各自的。

  return (
    
app组件
{store.name}
{store.price}
) } export default App //son组件中=========================================================================== import React, { useReducer } from 'react' // 引入自己定义的storehook import usestore from '../store.jsx' function Son() { let [store, dispatch] = usestore() console.log(store); // 使用action将name的值改为海绵宝宝好杯子 let action = { type: "NAME", value: "海绵宝宝好杯子" } // 点击按钮,则调用dispatch函数, let change = () => { dispatch(action) } return (
son组件
{store.name}
) } export default Son

 问题:app组件和son组件中都有name属性,在son组件中点击按钮将name的值改变了,son页面的值改变了,但app组件没有改变。
          因为引进来的是一个函数,每一次调用的都是独立的结果,各各自是各自的。

所以要利用usecontext、插槽、usereducer来实现仓库

在main.jsx文件中引入刚刚封装的store

七、useRef 

八、自定义Hoook

含义将官方的hooks搭配使用设计出自己的use开头的函数,该函数具备自定义的功能,就是自定义hook。

九、高阶组件(HOC)

含义:函数调用后返回了一个组件,这个函数就是高阶组件

HOC是react中复用组件逻辑的一种高级技巧,HOC本身不是react api的一部分,只是一种基于react的组合特性而形成的一种设计模式,也就是说当调用函数后返回了一个函数,那么这个调用的那个函数就是高阶组件。


import React, { useState } from 'react'
function Son() {
    // cup这个组件返回的是一个jsx对象,所以是一个简单的组件
    function Cup() {
        let [obj, setobj] = useState({ name: "画面宝宝", price: 23, comment: "棒棒!!!" })
        return 
cup这个组件
{obj.name}
{obj.price}
{obj.comment}
} // HOC高阶组件:该函数返回的还是一个函数, function Phone() { // 返回的是cup这个函数组件,所以Phone是一个高阶组件 return Cup() } return (
Son组件
phone的高阶组件
) } export default Son

为什么要使用HOC高阶组件呢

        1.抽取重复的代码,实现组件的重复使用,也就是相同功能的组件重复使用

    

         2.根据条件渲染,控制组件的渲染逻辑:权限控制

你可能感兴趣的:(react.js,前端,前端框架)