react的hook钩子

react组件有两种写法一种是export default直接暴露一个function,还有一种是直接定义一个class类然后继承react库的Component类这两种方式来创建react组件。

对于class类创建react组件的方式来说可以直接定义组件的this.state,这样在render中return的jsx模板中就可以直接this.state调用,以及this.setState来更新this.state的参数并更新视图。!!!注意:class类创建的组件不能使用hook。

对于function创建react组件的方式不需要继承react库的Component类,而且不能直接通过this.state设置组件中的数据。这时候就需要用到hook了,hook是针对function创建react组件设置state数据使用的。!!!注意:function创建react组件不能使用this.state。
 

下面直接看代码吧

import React, { useState,useEffect } from 'react';

export default function Hook() {
  const [count, setCount] = useState(0);
  const [boller, setBoller] = useState(false)
  useEffect(() => {
    console.log('count')
  },[count])
  useEffect(() => {
    console.log('boller')
  },[boller])
  return (
    <div>
      <p> {count} {boller ? 'true' : 'false'} </p>
      <button onClick={() => {setCount(count + 1); setBoller(!boller)}}>
        点击
      </button>
    </div>
  );
}

hook需要用到react库的useState;定义一个hook数组,数组第一个传入的是state数据的名字,数组第二位是方法用来更新这个hook的数据;useState传入的是该hook的默认值。这样一个hook就定义完成了,点击button按钮调用对应更新hook的方法来改变hook和更新视图。

上面还提到了useEffect这个api,这个api主要是在更新这个hook的数据的方法执行后的一个回调方法可以传入两个参数,第一个参数是一个callback回调函数;第二个参数是对应哪写hook更新后才执行不传为所有hook更新都执行,形式为数组。useEffect有点类似vue中的watch监听。

最近的taro项目里面学到了不少之前react中没有注意到的知识点,果然自学的认知还是比较局限的。估计这次taro的项目做完react就能上手项目了。加油!!!

#2019.9.23
如果useEffect中的第二个参数传入空数组则被视为是类似于componentdidmounted这样的生命周期,如果第一个传入的callback参数return一个方法则视为类似于componentdidUnmounted生命周期函数

useEffect(() => {
    console.log('页面首次加载')
    return () => {
      console.log('页面卸载的事件')
    }
  },[])

#2020.1.06
这段时间比较有空记录一下之前积累的知识点
除了上面的两个常用的hook之外还有useContext,useReducer,useCallback,useMemo,useRef,useImperativeHandle,useLayoutEffect这几个,虽然比较不常用但是还是要学习下的
useContext:类似redux和mobx全局store的功能
目录结构:

context.js:

import React from 'react'

const MyContext = React.createContext()

export default MyContext

父组件:通过context.js暴露的组件对象创建一个Provider组件并传入value参数(这是给父组件下子组件的共享数据)

import React, {
  useState,
  useEffect,
  useContext,
} from 'react';
import { withRouter } from 'react-router-dom'
import HookApi from './components/hookApi'
import StateContext from './context.js'


function Hookcom (props) {
  const [count, setCount] = useState(0);
  const [boller, setBoller] = useState(true)
  useEffect(() => {
    console.log(context)//useContext
  }, [])
  return (
    <div>
      <StateContext.Provider value={{
        name: count,
        changeName: (value) => {
          setCount(value)
        }
      }}>
        <HookApi Cref={childRef}>
          <HookApi.Con>423423421111111111111111113</HookApi.Con>
          <HookApi.Con>23423423423424234</HookApi.Con>
        </HookApi>
      </StateContext.Provider>
    </div>
  );
}
export default withRouter(Hookcom)

子组件 :useContext接受一个由React.createContext()返回的组件对象


import React, {
  useContext
} from 'react';
import StateContext from '../context.js'

function HookApi(props) {
  const ContextState = useContext(StateContext)
  return (
    <div>
      <div
        onClick={() => {
          ContextState.changeName(123456)
        }}>
        {ContextState.name}
      </div>
    </div>
  );
}

export default HookApi

useReducer:类似redux通过发布dispatch触发数据更新

import React, {
  useReducer
} from 'react';
import store from '../../mobxStore/mobx'

function reducerFn(value, action) {//dispatch为操作
  console.log(value, action.type)//value初始值,reducer为结果
  switch (action.type) {
    case 'increment':
      return { num: value.num + 1, name: 12 };
    case 'decrement':
      return { num: value.num - 1, name: 1112 };
    default:
      throw new Error();
  }
}

function Hookcom(props) {
  const [reducer, dispatch] = useReducer(reducerFn, { num: 1, name: 1212 })//传入第一个参数为回调第二个为初始值,对比useState更适合处理较为复杂的数据,useReducer 还能给那些会触发深更新的组件做性能优化
  useEffect(() => {
    console.log(reducer)//useReducer
  }, [])
  return (
    <div>
      <button onClick={() => {
        dispatch({ type: 'increment' })
      }}>
        点击
      </button>
    </div>
  );
}
export default Hookcom

useCallback:在数据更新之后执行的方法

import React, {
  useCallback,
  useMemo
} from 'react';
import store from '../../mobxStore/mobx'

function countCb() {
  console.log('更新了count')
}

const con = React.createContext({ ...store })//useContext
function Hookcom(props) {
  const [count, setCount] = useState(0);
  useCallback(countCb(), [count])//useCallback在count改变时触发可以避免非必要渲染
  useEffect(() => {
    console.log(context)//useContext
  }, [])
  return (
    <div>
      <button onClick={() => {
        setCount(count + 1);
      }}>
        点击
      </button>
    </div>
  );
}
export default Hookcom

useMemo在count改变时触发可以避免非必要渲染(类似vue的计算属性)

import React, {
  useCallback,
  useMemo
} from 'react';
import store from '../../mobxStore/mobx'

function countCb() {
  console.log('更新了count')
  return 1234
}

const con = React.createContext({ ...store })//useContext
function Hookcom(props) {
  const [count, setCount] = useState(0);
  useCallback(countCb(), [count])//useCallback在count改变时触发可以避免非必要渲染
  const newComputedValue = useMemo(() => countCb(), [count]);//useMemo在count改变时触发可以避免非必要渲染(类似vue的计算属性)
  useEffect(() => {
    console.log(context)//useContext
  }, [])
  return (
    <div>
      <button onClick={() => {
        setCount(count + 1);
      }}>
        点击
      </button>
    { newComputedValue }
    </div>
  );
}
export default Hookcom

useRef,useImperativeHandle:这两个放到一起来说,主要是hook进行父子组件间的通信
父组件(useRef

import React, {
  useRef
} from 'react';

function Hookcom(props) {
  const childRef = useRef(); //父组件直接调用子组件设置,子组件中使用useImperativeHandle来设置对应要对接通信的数据
  useEffect(() => {
    console.log(childRef)//useRef
  }, [])
  return (
    <div>
      <HookApi Cref={childRef}>
      </HookApi>
      <button onClick={() => {
        childRef.current.handleClick()//触发子组件方法
      }}>
        点击
      </button>
    </div>
  );
}
export default Hookcom

子组件(useImperativeHandle


import React, {
  useImperativeHandle
} from 'react';

function HookApi(props) {
  useImperativeHandle(props.Cref, () => ({//hook写法父组件直接调用子组件方法
    handleClick: () => {
      console.log('子组件的方法被父组件调用',a)
    },
    b: 1322342
  }))
  const [a, setA] = useState(1) 
  return (
    <div>
      HookApi
      {/* {props.Cref.current.b}//错误写法取不到 */}
    </div>
  );
}

export default HookApi


useLayoutEffect

import React, {
  useLayoutEffect
} from 'react';


function Hookcom(props) {
  const [count, setCount] = useState(0);
  useLayoutEffect(() => {//和useEffect相同但是尽量使用useEffect
    console.log('数据发生变化')
  }, [count])
  return (
    <div>
      <button onClick={() => {
        setCount(count + 1);
      }}>
        点击
      </button>
    </div>
  );
}
export default Hookcom
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值