赞
踩
npx create-react-app my-app
以 use 开头的函数,只能在组件或自定义 Hook 的最顶层调用,不能在条件语句、循环语句或其他嵌套函数内调用 Hook。
在组件中添加状态变量
const [state, setState] = useState(initialState);
侦听状态变化,并执行相应逻辑
useEffect(setup, dependencies?)
不带参数的 useEffect 函数中不能使用useState方法来改变state,否则会触发无限循环
//不带参数,每次渲染后执行
useEffect(() => {
console.log("count", count);
});
当 useEffect 带参数时,参数的变化才会触发 useEffect 的执行,不变化不执行。可使用 useState
useEffect(() => {
console.log("count", count);
console.log("num", num);
}, [num]);
当 useEffect 传入空参数 [] 时,只有当第一次渲染(mount) 和不渲染(unmount)时执行。
useEffect(() => {
console.log("count", count);
}, []);
父子组件传递状态数据。createContext 能够创建组件间共享的上下文状态,然后通过 useContext 在组件中使用这些状态
import { createContext, useContext } from 'react'; const ThemeContext = createContext(null); export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Button>显示的主题</Button> </ThemeContext.Provider> ) } function Button({ children }) { const theme = useContext(ThemeContext); const className = 'button-' + theme; return ( <button className={className}> {children} </button> ); }
useReducer 是 useState 的替代方案。当你想更新的状态中包含多个子值时 或者 当你想更新一个状态,并且这个状态更新依赖于另一个状态的值时,可以使用useReducer,reducer 可以让你把组件内发生了什么(actions)和状态如何响应并更新分开表述。
结合useContext 可以实现 Redux 组件间共享状态管理
const [state, dispatch] = useReducer(reducer, initialArg, init?)
第三个参数如果没值,则将初始状态设置为initialArg。否则,将初始状态设置为呼叫init(initialArg)的结果
import { useReducer } from 'react'; function reducer(state, action) { switch (action.type) { case "minus_age": return { age: state.age > 0 ? (state.age - 1) : 0 }; default: return { age: state.age + 1 }; } } export default function Counter() { const [state, dispatch] = useReducer(reducer, { age: 42 }); return ( <> <button onClick={() => { dispatch({ type: 'add_age' }) }}> Add age </button> <button onClick={() => { dispatch({ type: 'minus_age' }) }}> Minus age </button> <p>Hello! You are {state.age}.</p> </> ); }
和useState的setState不一样的是,useReducer返回的dispatch函数是用来触发某些改变state的action而不是直接设置state的值
相当于计算属性
const cachedValue = useMemo(calculateValue, dependencies)
export default function Counter() {
const clickFn = useMemo(() => {
let sum = 0;
for (let i = 0; i < 100*count; i++) {
sum += i;
}
return sum;
},[count]);
//当依赖的count发生改变才去重新计算,return值出来
return(
<div>获得总数{clickFn}</div>
)
}
避免子组件不必要的重新渲染,依赖数据改变传入新函数否则保留原函数
const cachedFn = useCallback(fn, dependencies)
useMemo和useCallback接收的参数都是一样,都是在其依赖项发生变化后才执行,都是返回缓存的值。而useEffect没有返回
区别在于useMemo返回的是函数运行的结果,useCallback返回的是函数。
useCallback(fn, deps) 与 useMemo(() => fn, deps). 是等价的,
useRef 返回一个引用了DOM的对象,返回的对象将在组件的整个生存期内持续存在。相当于为this赋值
const ref = useRef(initialValue)
import { useRef } from 'react'; export default function Form() { const inputRef = useRef(null); function handleClick() { //点击使input框获取焦点 inputRef.current.focus(); } return ( <> <input ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> ); }
useRef和createRef的区别是createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用,可以在 useRef 对象上存放缓存的值。
转发ref,将dom暴露给父组件
import { forwardRef, useRef } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { return ( <label> {props.label} <input ref={ref} /> </label> ); }); export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); } return ( <form> <MyInput label="Enter your name:" ref={ref} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
使用forwardRef和useImperativeHandle限制父组件调用子组件的Api
import { forwardRef, useRef, useImperativeHandle } from 'react'; const MyInput = forwardRef(function MyInput(props, ref) { const inputRef = useRef(null); useImperativeHandle(ref, () => { return { focus() { inputRef.current.focus(); }, scrollIntoView() { inputRef.current.scrollIntoView(); }, }; }, []); return <input {...props} ref={inputRef} /> }); export default function Form() { const ref = useRef(null); function handleClick() { //父组件获得了 MyInput 的 ref,能通过该 ref 来调用 focus 和 scrollIntoView 方法 //但是它的访问是受限的,无法读取或调用下方 <input> DOM 节点的其他所有属性和方法 ref.current.focus(); // 下方代码不起作用,因为 DOM 节点并未被暴露出来: // ref.current.style.opacity = 0.5; } return ( <form> <MyInput label="Enter your name:" ref={ref} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
ref有一个current属性,可以对这个属性进行操作,用于获取DOM元素和保存变化的值。
不要滥用ref,仅在没法通过 prop 来表达 命令式 行为的时候才使用 ref,比如滚动到指定节点、聚焦某个节点、触发一次动画、选择文本等
如果可以通过prop实现,就不要使用ref ,useEffect 可以通过 prop 来暴露一些命令式的行为
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。