HOOK这个单词的意思是钩子,用来将外部功能“钩”进来

四个最常用的钩子

  • useState
  • useContext
  • useReducer
  • useEffect

useState() 状态钩子

  • useState()用于维函数引入状态state ,纯函数不能有状态,所以状态放在钩子里面 ```javascript //引入钩子组件 import React, { useState } from “react”;

export default function Button() { //用钩子引入state状态 //数组的第一个成员是一个变量,指向状态初始值,第二个值是一个函数,用来更新状态,约定是 //set前缀加上状态的变量名 const [buttonText, setButtonText] = useState(“Click me, please”); //改变state状态 function handleClick() { return setButtonText(“Thanks, been clicked!”); } return ; }

  1. <a name="S4YY3"></a>
  2. ### useContext()共享状态钩子
  3. ```javascript
  4. import React, { useContext } from "react";
  5. import ReactDOM from "react-dom";
  6. //创建一个Context
  7. const AppContext = React.createContext({});
  8. const Navbar = () => {
  9. //子组件通过useContext() 钩子用来引入Context对象,从中获取username属性
  10. const { username } = useContext(AppContext)
  11. return (
  12. <div className="navbar">
  13. <p>AwesomeSite</p>
  14. <p>{username}</p>
  15. </div>
  16. )
  17. }
  18. const Messages = () => {
  19. const { username } = useContext(AppContext)
  20. return (
  21. <div className="messages">
  22. <h1>Messages</h1>
  23. <p>1 message for {username}</p>
  24. <p className="message">useContext is awesome!</p>
  25. </div>
  26. )
  27. }
  28. //使用AppContext.Provider 提供一个Context对象,这个对象可以被组建共享
  29. function App() {
  30. return (
  31. <AppContext.Provider value={{
  32. username: 'superawesome'
  33. }}>
  34. <div className="App">
  35. <Navbar />
  36. <Messages />
  37. </div>
  38. </AppContext.Provider>
  39. );
  40. }
  41. const rootElement = document.getElementById("root");
  42. ReactDOM.render(<App />, rootElement);

userReducer(): action 钩子

  1. import React, { useReducer } from "react";
  2. import ReactDOM from "react-dom";
  3. //Reducer修改state返回新的state
  4. const myReducer = (state, action) => {
  5. switch(action.type) {
  6. case('countUp'):
  7. return {
  8. ...state,
  9. count: state.count + 1
  10. }
  11. default:
  12. return state
  13. }
  14. }
  15. function App() {
  16. //数组的第一个成员是当前状态,第二个成员是发送action的dispatch函数
  17. const [state, dispatch] = useReducer(myReducer, { count: 0 })
  18. return (
  19. <div className="App">
  20. <button onClick={() => dispatch({ type: 'countUp' })}>
  21. +1
  22. </button>
  23. <p>Count: {state.count}</p>
  24. </div>
  25. );
  26. }
  27. const rootElement = document.getElementById("root");
  28. ReactDOM.render(<App />, rootElement);

由于 Hooks 可以提供共享状态和 Reducer 函数,所以它在这些方面可以取代 Redux。但是,它没法提供中间件(middleware)和时间旅行(time travel),如果你需要这两个功能,还是要用 Redux。

useEffect():副作用钩子

  • 用来引入有副作用的操作,最常见的就是向服务器请求数据,之前放在componentDidMount里面的代码,现在可以放在这里
  • useEffect接收两个参数,第一个是函数,一步的操作代码放在里面,第二个是一个数组,用于给出Effect的依赖项,只要这个数组发生变化,useEffect()就会执行,第二个参数省略,每次组件渲染时,就会执行useRffect ```javascript import React, { useState, useEffect } from “react”; import ReactDOM from “react-dom”;

const Person = ({ personId }) => { const [loading, setLoading] = useState(true); const [person, setPerson] = useState({}); //用来执行有副作用的操作 useEffect(() => { setLoading(true); fetch(https://swapi.co/api/people/${personId}/) .then(response => response.json()) .then(data => { setPerson(data); setLoading(false); }); }, //第二个参数为数组,依赖的参数发生变化就会执行useEffect [personId]);

if (loading === true) { return

Loading …

; }

return (

You’re viewing: {person.name}

Height: {person.height}

Mass: {person.mass}

); };

function App() { const [show, setShow] = useState(“1”);

return (

Show:
); }

const rootElement = document.getElementById(“root”); ReactDOM.render(, rootElement);

  1. <a name="Fep7i"></a>
  2. ### useMemo 防止子组件重复执行
  3. 父组件状态发生变化,子组件也会重新执行一次,那么要防止子组件方法在任何情况下调用,我们可以使用useMemo来对方法进行阻止
  4. ```javascript
  5. import React ,{useMemo} from 'react'
  6. //子组件接收一个count,那么只有在count发生变化才会触发这个函数,否则就跳过
  7. function Dom({count}){
  8. let cc = useMemo(()=>{
  9. return count *2
  10. },[count])
  11. return <div>
  12. <h1>Dom {count}------{cc}</h1>
  13. </div>
  14. }
  15. export default Dom

useRef

useRef 可以用来保存DOM和变量,进行一个缓存。

  1. const inp = useRef(null)//初始化一个inp变量
  2. return (
  3. <div>
  4. <input type='text' ref={inp} />{/* 保存DOM节点到inp上 */}
  5. <button
  6. onClick={() => {
  7. console.log(inp.current.value)
  8. //打印出来输入的值
  9. }}>
  10. 改变一下
  11. </button>
  12. </div>
  13. )

使用useContext、useReducer封装一个类似于redux仓库

  • 第一步 创建store.js ```javascript import { createContext } from “react”; //定义共享数据 export const Context =createContext(null); //定义仓库初始值 export const defayltState={ count:0 } //定义修改数据方法 export default (state,action)=>{ switch(action.type){
    1. case('add'):
    2. return {
    3. ...state,
    4. count:state.count + 1
    5. }
    6. default:
    7. return state
    } }
  1. - 第二步 父组件挂载context
  2. ```javascript
  3. /** @format */
  4. import React, { useState,useReducer } from 'react'
  5. import Son from './son'
  6. //引入配置
  7. import myReducer,{defayltState,Context} from './store'
  8. export default function Father() {
  9. const [state,dispatch] = useReducer(myReducer,defayltState)
  10. //调用后数组第一个成员是当前状态,第二个是发送action的dispatch函数
  11. return (
  12. //通过context 挂载共享属性
  13. <Context.Provider value={{...state,dispatch}}>
  14. <h1>{state.count}</h1>
  15. <button onClick={()=>dispatch({type:'add'})}>add 1</button>
  16. <Son></Son>
  17. </Context.Provider>
  18. )
  19. }
  • 第三步 在子组件调用 ```javascript import React,{useContext,useEffect} from ‘react’ import {Context} from ‘./store’;//引入context

function Son(){ const con = useContext(Context)//拿到数据 useEffect(()=>{ setTimeout(()=>{ console.log(‘200’) },1000) },[])//数组为空只有初始化页面执行,不传递参数每次数据更改都会执行 return

this is son—-{con.count}
} export default Son ```