1:useState
import React, { useState } from 'react';function App() {const [ Switch, setSwitch ] = useState("打开!");const newName = () => {Switch === "打开"? setSwitch("关闭"):setSwitch("打开");}return (<div><p>现在是:{ Switch } 状态</p><button onClick={ newName }>Change Me!</button></div>);
}export default App;
多个参数处理
const [state, setState] = useState({ text: "", checked: false });const updateState = partialState =>setState(oldState => ({...oldState,...partialState
}));return (<div><inputtype="checkbox"checked={state.checked}onChange={() => updateState({ checked: !state.checked })}/></div>
)
2:useEffect
useEffect 方法代替了 class 类组件的 componentDidMount
, componentDidUpdate
,componentWillUnmount
import React, { useState, useEffect } from 'react';function App() {const [ Switch, setSwitch ] = useState("打开!");const [ Num, setNum ] = useState(0);const newName = () => {Switch === "打开"? setSwitch("关闭"):setSwitch("打开");};const add = () => {setNum(Num + 1);};const minus = () => {setNum(Num - 1);};useEffect(() => {console.log("状态改变了!");});return (<div><p>现在是:{ Switch } 状态</p><button onClick={ newName }>Change Me!</button><p>Num { Num }</p><button onClick={ add }>加一</button><button onClick={ minus }>减一</button></div>);
}export default App;
上面这个例子他会再初次渲染的时候打印 改变了状态 并且每次状态改变的时候都打印 改变了状态
那么这样的用法就是 componentDidMount
, componentDidUpdate
,的使用
useEffect 第二个参数:
添加的第二个参数为监听的对象
useEffect(() => {console.log("状态改变了!");},[Num]);
当Num值发生变化时打印“状态改变了”
useEffect 的闭包使用:
useEffect(() => {console.log('装载了')return () => {console.log('卸载拉');};});
在 useEffect 中我们可以做两件事情,组件挂载完成时候,还有组件卸载时,只要在 useEffect 中使用闭包,在闭包中做我们想要在组件卸载时需要做的事就可以。
useEffect 挂载、更新、卸载同时使用:
import React, { useState, useEffect } from 'react'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'function Index() {useEffect(() => {console.log("欢迎来到Index页面");return () => {// 解绑console.log("您离开了Index页面");}}, []);return <h2>首页</h2>
}function List() {useEffect(() => {console.log("欢迎来到List页面");return () => {// 解绑console.log("您离开了List页面");}}, []);return <h2>列表页</h2>
}function UseEffect() {const [count, setCount] = useState(0);useEffect(() => {console.log('useEffect');return () => {console.log("==========");}}, [count]);return (<div><p>You clicked {count} times!</p><button onClick={() => { setCount(count + 1) }}>Click me</button><Router><ul><li><Link to="/">首页</Link></li><li><Link to="/list">列表</Link></li></ul><Route path="/" exact component={Index}></Route><Route path="/list" component={List}></Route></Router></div>)
}export default UseEffect;
3:useRef 使用:
使用场景:1、设置、获取dom元素值 2、保存变量
import React,{ useState, useEffect, useRef } from 'react';function UseRef () {const inputEl = useRef(null);const onButtonClick = () => {// 设置input值inputEl.current.value = "hello react-hooks";console.log('inputEl', inputEl);}const[ text,setText ] = useState("useRef");// 保存变量const textRef = useRef();useEffect(() => {textRef.current = text;console.log('textRef.current', textRef.current);});return (<><input ref={inputEl} type="text" /><button onClick={onButtonClick}>在input上边展示文字</button><br /><br /><input value={text} onChange={(e) => {setText(e.target.value)}}/></>)
}export default UseRef;
打印结果:3 3 3 3
import React, { useState, useEffect } from 'react';function App() {const [ Num, setNum ] = useState(0);useEffect(() => {console.log(Num);});return (<div><p>You clicked { Num } times</p><button onClick={ () => { setNum(Num + 1)}}>点击三次</button></div>);
}export default App;
打印结果:0 1 2 3
4: useContext 使用
使用场景:如果需要在组件之间共享状态,可以使用useContext()
import React, { useState, createContext, useContext } from 'react'const CountContext = createContext();function Counter() {const count = useContext(CountContext);return (<h2>{count}</h2>)
}function UseContext() {const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => { setCount(count + 1) }}>click me</button><CountContext.Provider value={count}><Counter /></CountContext.Provider></div>)
}export default UseContext;
5: useReducer 使用
useReducer 提供类似 Redux 的功能,引入 useReducer 后,useReducer 接受一个 reducer 函数作为参数,reducer 接受两个参数一个是 state 另一个是 action 。然后返回一个状态 count 和 dispath,count 是返回状态中的值,而 dispatch 是一个可以发布事件来更新 state 的。
import React, { useReducer } from 'react'function UseReducer() {const [count, dispatch] = useReducer((state, action) => {switch (action.type) {case "add":return state + 1;case "sub":return state - 1;default:return state;}}, 0);return (<div><h2>现在的分数{count}</h2><button onClick={() => dispatch({ type: "add" })}>Increment</button><button onClick={() => dispatch({ type: "sub" })}>Decrement</button></div>)
}export default UseReducer;
6: usereducer 、useContext 实现redux功能
ShowArea.js
import React, { useContext } from 'react'
import { ColorContext } from './Color'
function ShowArea() {const { color } = useContext(ColorContext);return (<div style={
{ color: color }}>字体颜色为{color}</div>)
}export default ShowArea;
Buttons.js
import React, { useContext } from 'react'
import { ColorContext, UPDATE_COLOR } from './Color'function Buttons() {const { dispatch } = useContext(ColorContext);return (<div><button onClick={() => { dispatch({ type: UPDATE_COLOR, color: "red" }) }}>红色</button><button onClick={() => { dispatch({ type: UPDATE_COLOR, color: "yellow" }) }}>黄色</button></div>)
}export default Buttons;
Color.js
import React, { createContext, useReducer } from 'react';export const ColorContext = createContext({});export const UPDATE_COLOR = "UPDATE_COLOR";const reducer = (state, action) => {switch (action.type) {case UPDATE_COLOR:return action.color;default:return state;}
}export const Color = props => {const [color, dispatch] = useReducer(reducer, "blue");return (<ColorContext.Provider value={
{ color, dispatch }}>{props.children}</ColorContext.Provider>)
};
Example.js
import React from 'react'
import ShowArea from './ShowArea'
import Buttons from './Buttons'
import { Color } from './Color'function ReducerExample() {return (<div><Color><ShowArea /><Buttons /></Color></div>)
}export default ReducerExample;
7: useMemo 使用
未使用useMemo场景:
父组件:
function App() {const [name, setName] = useState('名称')const [content,setContent] = useState('内容')return (<><button onClick={() => setName(new Date().getTime())}>name</button><button onClick={() => setContent(new Date().getTime())}>content</button><Button name={name}>{content}</Button></>)
}
子组件:
function Button({ name, children }) {function changeName(name) {console.log('11')return name + '改变name的方法'}const otherName = changeName(name)return (<><div>{otherName}</div><div>{children}</div></>)
}
分析:
不管我们是改变name或者content的值,我们发现 changeName的方法都会被调用。
是不是意味着 我们本来只想修改content的值,但是由于name并没有发生变化,所以无需执行对应的changeName方法。但是发现他却执行了。 这是不是就意味着性能的损耗,做了无用功。
优化后的子组件:
function Button({ name, children }) {function changeName(name) {console.log('11')return name + '改变name的方法'}const otherName = useMemo(()=>changeName(name),[name])return (<><div>{otherName}</div><div>{children}</div></>)
}export default Button
总结:
这个时候我们点击 改变content值的按钮,发现changeName 并没有被调用。
但是点击改变name值按钮的时候,changeName被调用了。
所以我们可以使用useMemo方法 避免无用方法的调用
8: useCallback 及自定义hooks
自定义hooks useWinSize以及组件中使用useWinSize
// 自定义hooks
import React,{ useState, useEffect, useCallback } from 'react'function useWinSize () {const [ size,setSize ] = useState({width: document.documentElement.clientWidth,height: document.documentElement.clientHeight,});const onResize = useCallback( ()=> {setSize({width: document.documentElement.clientWidth,height: document.documentElement.clientHeight,});});useEffect(() => {window.addEventListener("resize",onResize);return () => {window.removeEventListener("resize",onResize);}},[]);return size;
}function UseCallback (){const size = useWinSize();return (<h3>页面size{size.width}*{size.height}</h3>)
}export default UseCallback;
9:自定义hooks 实现获取窗口大小
/** 自定义 useWidowSize hooks */import { useState, useEffect } from 'react';export const useWindowSize = (props) => {const [ width, setWidth ] = useState('0px');const [ height, setHeight ] = useState('0px');useEffect(() => {setWidth(document.documentElement.clientWidth + 'px');setHeight(document.documentElement.clientHeight) + 'px';},[]);useEffect(() => {const handleResize = () => {setWidth(document.documentElement.clientWidth + 'px');setHeight(document.documentElement.clientHeight) + 'px';};window.addEventListener('resize',handleResize, false);return () => {window.removeEventListener('resize', handleResize, false);}},[])return [width, height];
}/** 组件中使用自定义hooks */import React form 'react';const Parent = () => {const [ width, height ] = useWindowSize(props);return (<div>size: {width} * {height}</div>)
}