React Hooks小结

186 阅读2分钟

先从最常用的useState开始。

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

const Count = () => {
 /**
  * const [state, setState] = useState(initState)
  * usetState(initState)接收一个参数作为state的初始值,返回state值和设置(改变)state的函数setState
  */
 const [count, setCount] = useState(0)
 const [clickTimes, setClickTimes] = useState(0)
 let log = `count:${count},clickTime:${clickTimes}` //每点击一次,log都会发生变化
 return (
   <div>
     <p>{log}</p>
     <button onClick={() => {
       setCount(count+1)
       setClickTimes(clickTimes+1)
     } }>count加一</button>
     <button onClick={() => {
       setCount(count-1)
       setClickTimes(clickTimes+1)
     }}>count减一</button>
     <button onClick={() => {
       setCount(count)
       setClickTimes(clickTimes+1)
     }}>count不变</button>
   </div>
 )
}
export default Count

上面是setState的基本用法。现在如果有一个新需求,就是只有在变量count发生变化的时候,变量log才发生变化,那么就引出了useMemo

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


const Count = () => {
    ...
   let log = useMemo(() => {
       return `count:${count},clickTime:${clickTimes}`
   },[count])
   ...
}
  

再来一个新的需求,在每次count发生变化之后,每隔count秒,输出一次log。这就引出引出下一个hookuseEffect

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

const Count = () => {
    ...
   useEffect(() => {
       let timer =  setInterval(() => {
         console.log(`每${count}秒,打印一次`)
       }, 1000*count);
       return () => {
         clearInterval(timer)//执行清除定时器操作,类似于componentWillUnmount
       }
   },[count])//只有在count发生变化的时候才会执行useEffect
   ...
}

在接下来看一看useContext,直接看官方文档给出的示例:

import React, {  useContext } from 'react';

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);

  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

而如果不使用useContext,可以这样:

...
class ThemedButton extends React.Component{
  static contextType = ThemeContext
  render(){
    let theme = this.context    
    return (
      <button style={{ background: theme.background, color: theme.foreground }}>
        I am styled by theme context!
      </button>
    );
  }
}
...

或者可以这样:

function ThemedButton() {

  return (
    <ThemeContext.Consumer>
      {
        theme => (
          <button style={{ background: theme.background, color: theme.foreground }}>
            I am styled by theme context!
          </button>
        )
      }
    </ThemeContext.Consumer>
    
  );
}

接下来是useReducer,结合ProvideruseContext,可以有替代redux的效果:

import React,{useReducer, useContext, useMemo} from 'react'

function init(initUserList){
  return {usersList:initUserList}
}

let reducer = function(state, action){
  console.log(state, action)
  switch (action.type){
    case 'changeName':
      let usersList = state.usersList.map(item => {
        if(item.id === action.payload.id){
          item.userName = action.payload.newValue
        }
        return item
      })
      return {usersList}
    default:
      throw new Error()
  }

}

let UsersContext = React.createContext({usersList:[],dispatch:function(){}})

let Page = function({initUserList}) {

  const [state, dispatch] = useReducer(reducer, initUserList, init)
 
  return (
    <UsersContext.Provider value={{usersList:state.usersList,dispatch:dispatch}}>
      <Parent>
      </Parent>
    </UsersContext.Provider>
  )

}
let Parent = function(){
  return (
    <div>
        <UsersList></UsersList>
    </div>
  )
}
let UsersList = function(){
  let {usersList,dispatch} = useContext(UsersContext)
  return (
    <ul>
      {
        usersList && usersList.map(item => {
          let {userName, userAge, id} = item
          return (
            <li key={id}>
              <input type="text" onChange={(event) => dispatch({type:'changeName',payload:{id,newValue:event.target.value}})} value={userName}/>
              <span>userAge:{userAge}</span>
              <span>id:{id}</span>
            </li>
          )
        })
      }
    </ul>
  )
}



let WrapperPage = function(){
  let initUserList = [
    {userName:'jack', userAge:10, id:0},
    {userName:'tom', userAge:12, id:1},
    {userName:'suna', userAge:13, id:2},
  ]
  return (
    <Page initUserList={initUserList}></Page>
  )
}

export default WrapperPage

算了,懒得写了,就写到这里...

React Hooks

看完这篇,你也能把 React Hooks 玩出花