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>
<input
type="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>
)
}