- useState用法
- useREducer用法
- useContent用法
- useEffect & useLayoutEffect的区别用法
- useMemo && React.memo && useCallback用法
1.useState用法
- useState使用状态
- 注意事项
- 不可以局部更新
- 如果state是一个对象,setState不会自动合并属性
- 如果setState(obj)如果地址不变,react就会认为数据没变
- useState可以接收函数
- 不可以局部更新
const [state,setState] = useState(()=>{
return {}
})
案例
function App() {
const [user,setUser] = useState({name:'小明', age: 18})
const onClick = ()=>{
setUser({
...user,
name: '小红'
})
}
return (
<div className="App">
<h1>{user.name}</h1>
<h2>{user.age}</h2>
<button onClick={onClick}>Click</button>
</div>
);
}
2. useREducer用法
- 可以理解成useState的复杂版
const initial = {
n: 0
};
const reducer = (state, action) => {
if (action.type === "add") {
return { n: state.n + action.number };
} else if (action.type === "multi") {
return { n: state.n * 2 };
} else {
throw new Error("unknown type");
}
};
function App() {
const [state, dispatch] = useReducer(reducer, initial);
const { n } = state;
const onClick = () => {
dispatch({ type: "add", number: 1 });
};
const onClick2 = () => {
dispatch({ type: "add", number: 2 });
};
return (
<div className="App">
<h1>n: {n}</h1>
<button onClick={onClick}>+1</button>
<button onClick={onClick2}>+2</button>
</div>
);
}
3. useContent用法
- useContent全局变量是全局的上下文
- 注意
- 不是响应式的
- 在一个模块将C里面的值改变后,另一个模块不会感知这个变化
- 不是响应式的
const C = createContext(null);
function App() {
console.log("App 执行了");
const [n, setN] = useState(0);
return (
<C.Provider value={{ n, setN }}>
<div className="App">
<Baba />
</div>
</C.Provider>
);
}
function Baba() {
const { n, setN } = useContext(C);
return (
<div>
我是爸爸 n: {n} <Child />
</div>
);
}
function Child() {
const { n, setN } = useContext(C);
const onClick = () => {
setN(i => i + 1);
};
return (
<div>
我是儿子 我得到的 n: {n}
<button onClick={onClick}>+1</button>
</div>
);
}
4. useEffect & useLayoutEffect的区别用法
- useEffect 副作用
- 对环境的改变就是副作用,如修改了document.title
- 用途
- 在函数组件中模拟componentDidMount\componentDidUpdate\componentWillUnmount
- 以上三种用途可以同时存在
- 当多个useEffect出现时,会按照出现的次序执行
function App(){
const [n,setN] = useState(0)
const add = ()=>{
setN((state)=>{return state+1})
}
useEffect(()=>{
console.log("第一次渲染执行")
},[])
useEffect(()=>{
console.log("n发生变化是执行")
},[n])
useEffect(()=>{
return ()=>{
console.log("页面销毁时执行")
}
},[])
return(
<div>
{n}
<button onClick={add}>add</button>
</div>
)
}
useLayoutEffect
用法和useEffect完全相同 案例一
const App = () => {
const [value, setValue] = useState(0);
useEffect(() => {
document.querySelector("#x").innerText = `value: 1000`;
}, [value]);
return (
<div id="x" onClick={() => setValue(0)}>
value: {value}
</div>
);
};
上面的代码会在会浏览器开始显示value:0,然后在显示value:100;(如果想让浏览器直接显示value:100)
useLayoutEffect(() => {
document.querySelector("#x").innerText = `value: 1000`;
}, [value]);
useEffect和useLayoutEffect的区别
- useEffect在render之后执行,所以页面会先显示value:0然后在更新为value:1000
- useLayoutEffects在render之前执行,在页面渲染之前value已经被更改为1000; 固两者这的区别就是执行时机的区别,在开发过程中推荐使用useEffect
5. useMemo && React.memo && useCallback用法
- useMemo为了解决React的多余渲染
- 场景 当App组件引用子组件时,当App组件更新时会重新调用App()重新并重新渲染子组件,这就导致了子组件在没有任何改变就被重新渲染了.
- useMemo 搭配React.memo使用
function App(){
console.log("调用了app")
const [n,setN] = useState(0)
const [m,setM] = useState(0)
const addN = ()=>{
setN((state)=>{
return state+1
})
}
const addM = useMemo(()=>{
return ()=>{
setM((state)=>{
return state+1
})
}
},[m])
return (
<div>
<div>
prend:{n}
<button onClick={addN}>addN</button>
</div>
{/*<Child2 data={m} onClick={addM}></Child2>*/}
<Child2 data={m} onClick={addM}></Child2>
</div>
)
}
const Child2 = React.memo((props)=>{
console.log("调用了CHild")
return(
<div>
Child: {props.data}
<button onClick={props.onClick}>addM</button>
</div>
)
})
usememo的语法糖 useCallback
//useMemo的语法糖 const addM =useCallback( ()=>{ setM((state)=>{ return state+1 }) },[m] )