lanyage-react-hooks-demo
v1.0.0
Published
- useState - useEffect - useContext - useReducer - useMemo - useCallback - useRef - 自定义hook
Downloads
2
Readme
React在16.18之后hooks新特性
- useState
- useEffect
- useContext
- useReducer
- useMemo
- useCallback
- useRef
- 自定义hook
useState,
useState用于设置状态。
const [count, setCount] = useState({
firstCount: initialCount1,
secondCount: initialCount2
});
useEffect。
useEffect用于执行副作用操作,其第一个参数是一个函数,用于执行副作用操作,如:绑定事件,操作DOM,根据某个状态来执行异步操作;第二个参数是一个数组,表示依赖的状态,如不传,则表示只会在初始render时执行一次。另外,其return一个函数,并在该函数中释放资源,如停止定时任务。
// 操作DOM
useEffect(() => {
console.log("use effect.");
document.title = `count ${count}`;
}, [count]);
// 根据userId的变化来执行这个操作
const [useId, setUserId] = useState(1001);
useEffect(() => {
// fetch, ajax, axios
}, [userId])
userContext
userContext类似于Java中的ThreadLocal,起到一个上下文的作用。
// producer
// App.jsx
export const XXXContext = React.createContext();
<XXXContext value={"xxx"}>
<OtherComponent />
</XXXContext>
// consumer
import {useContext} from 'react';
import {XXXContext} from 'App';
const xxx = useContext(XXXContext);
useReducer
useReducer是useState的替代品,通过action来触发状态的变化。结合useContext可以实现属性代理
import {useReducer, useContext} from 'react';
const initialState = 0;
const reducer = (state, action) => {
switch(action.type) {
case "increment":
return state + 1;
default:
return state;
}
};
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
// fetch, axios, ajax
fetch(`url`)
.then(response => {
dispatch({type: 'SUCCSSS', payload: response});
})
.catch(err => {
dispatch({type: 'ERROR'});
})
}, [id])
useMemo
useMemo用于内存优化,将函数返回结果在内存缓存起来,如果没有变化,就不会重新计算。
const Counter = () => {
const [count1, setCount1] = useState(0);
const [count2, setCount2] = useState(0);
// 当count1有变化,使用内存备忘录来记住count1计算出的值
const isEven = useMemo( () => {
let i = 0;
while(i < 2000000000) i++;
return count1 % 2 === 0;
}, [count1]);
return (
<div>
<div>
<button onClick={() => {
setCount1(d => d + 1);
}}>Count1: {count1}</button>
<span>{isEven ? "event" : "odd"}</span>
</div>
<div>
<button onClick={() => {
setCount2(d => d + 1);
}}>Count1: {count2}</button>
</div>
</div>
)
}
useCallback
React默认父组件的重新渲染会导致子组件的重新渲染。React在function的组件中,所有function都会在render时作为一个全新的function,但是大多数情况下我们不需要这样的函数,此时我们可以在组件上使用React.memo(component)并配合useCallback(() => {// change state code}, [field]), 这样可以减少很多自组件不必要的渲染。
import {useState, useMemo, useCallback} from 'react';
const Title = React.memo(function () {
console.log('Rendering Title')
return (
<h2>
useCallback Hook
</h2>
)
});
const Button = React.memo(
function({ handleClick, children }) {
console.log('Rendering button - ', children)
return (
<button onClick={handleClick}>
{children}
</button>
)
}
);
const Count = React.memo(
function({ text, count }) {
console.log(`Rendering ${text}`)
return <div>{text} - {count}</div>
}
);
function ParentComponent() {
const [age, setAge] = useState(25)
const [salary, setSalary] = useState(50000)
const incrementAge = useCallback(() => {
setAge(age + 1)
}, [age])
const incrementSalary = useCallback(() => {
setSalary(salary + 1000)
}, [salary])
return (
<div>
<Title />
<Count text="Age" count={age} />
<Button handleClick={incrementAge}>Increment Age</Button>
<Count text="Salary" count={salary} />
<Button handleClick={incrementSalary}>Increment Salary</Button>
</div>
)
}
useRef, 用于和DOM元素进行通信,或存储组件的某些属性如:this.xxx
// 和DOM元素通信
function FocusInput() {
const inputRef = useRef(null)
useEffect(() => {
inputRef.current.focus()
}, [])
return (
<div>
<input ref={inputRef} type="text" />
</div>
)
}
// 存储组件属性
function HookTimer() {
const [timer, setTimer] = useState(0)
const interValRef = useRef()
useEffect(() => {
interValRef.current = setInterval(() => {
setTimer(timer => timer + 1)
}, 1000)
return () => {
clearInterval(interValRef.current)
}
}, [])
return (
<div>
HookTimer - {timer} -
<button onClick={() => clearInterval(interValRef.current)}>Clear Timer</button>
</div>
)
}
自定义hook,自定义hook本质上是对原生hook的一种封装。
// 例1
function useDocumentTitle(count) {
useEffect(() => {
document.title = `Count ${count}`
}, [count])
}
// 例2
function useCounter(initialCount = 0, value) {
const [count, setCount] = useState(initialCount)
const increment = () => {
setCount(prevCount => prevCount + value)
}
const decrement = () => {
setCount(prevCount => prevCount - value)
}
const reset = () => {
setCount(initialCount)
}
return [count, increment, decrement, reset]
}
// 例3
function useInput(initialValue) {
const [value, setValue] = useState(initialValue)
const reset = () => {
setValue('')
}
const bind = {
value,
onChange: e => {
setValue(e.target.value)
}
}
return [value, bind, reset]
}
总结
如上就是React16.18之后提供的新特性,可以大大的减少代码量。