-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React hooks那些事儿 #248
Comments
useContext是什么意思?contextcontext: react中的context无需为每层组件手动添加props,就可以在组件树之间传递数据的方法。 例如:地区偏好,UI主题,当前认证用户
const value = useContext(MyContext) useContextconst value = useContext(MyContext) 这个value由距离当前组件最近的 使用了useContext的组件会在context值发生变化时重新渲染。 const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.light);
function App() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
更多关于React useContext的用法可以查看:React除了可以通过props传递数据以外,如何通过context方式传递数据? useMemo是什么意思?useMemoconst memoizedValue = useMemo(()=> computedExpensiveValue(a,b), [a,b]) memo(memoization)是什么意思? 传入一个“新建”函数和一个依赖数组。useMemo仅仅在其中一个依赖发生变化时重新计算记忆值。这个优化可以帮助避免每次渲染造成的昂贵计算。 传入到useMemo的函数会在渲染时运行。不要在useMemo中做渲染时不想做的事。例如,side effects在useEffect这个钩子中,而不时在useMemo。 如果传入空数组,每次渲染都会有新值被计算。 可以将useMemo用于性能优化,而不是语义保证。 在未来,react可能会选择忘记之前的一些记忆值,在下一次渲染时重新计算他们,例如释放离线组件的缓存没有useMemo,代码也依然可以运行,然后再用useMemo做性能优化。 useCallback是什么意思?这是一个React的hook。 const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
); 在[a,b]中的一个依赖发生变化时,回调触发。
相比于vue而言,useCallback或者说useMemo可以类比为对象属性批量watch或者是对象属性deep watch。 react的useCallback或者说useMemo,比vue的watch(单个),watch(deep)更加灵活。 useEffect与useCallback(useMemo)的区别是什么?浏览器执行阶段:可见修改(DOM操作,动画,过渡)->样式规则计算->计算空间和位置->绘制像素内容->多个层合成 执行时间不同useEffect在渲染完成后执行函数,更加准确的来说是在layout和paint完成之后。
useCallback(useMemo)在渲染过程中执行函数。
哪些适合在渲染完成后执行,哪些适合在渲染过程中执行渲染完成后执行:Mutations(DOM操作), subscriptions(订阅), timers, logging 一个例子阐明useEffect和useMemo的区别useMemo最主要解决的问题:怎么在DOM改变的时候,控制某些函数不被触发。 这是一个非常非常好的例子,更加详细的博文在这里:useMemo和useEffect有什么区别?怎么使用useMemo import React, {Fragment} from 'react'
import { useState, useEffect, useCallback, useMemo } from 'react'
const nameList = ['apple', 'peer', 'banana', 'lemon']
const Example = (props) => {
const [price, setPrice] = useState(0)
const [name, setName] = useState('apple')
function getProductName() {
console.log('getProductName触发')
return name
}
// 只对name响应
useEffect(() => {
console.log('name effect 触发')
getProductName()
}, [name])
// 只对price响应
useEffect(() => {
console.log('price effect 触发')
}, [price])
// memo化的getProductName函数 🧬🧬🧬
const memo_getProductName = useMemo(() => {
console.log('name memo 触发')
return () => name // 返回一个函数
}, [name])
return (
<Fragment>
<p>{name}</p>
<p>{price}</p>
<p>普通的name:{getProductName()}</p>
<p>memo化的:{memo_getProductName ()}</p>
<button onClick={() => setPrice(price+1)}>价钱+1</button>
<button onClick={() => setName(nameList[Math.random() * nameList.length << 0])}>修改名字</button>
</Fragment>
)
}
export default Example 点击价钱+1按钮(通过useMemo,多余的memo_getProductName ()没有被触发,只触发price相关的函数)
点击修改名字按钮(通过useEffect,只触发name相关)
总结useEffect面对一些依赖于某个state的DOM渲染时,会出现一些性能问题,而useMemo可以优化这个问题。 |
useRef如何解决空指针问题?通常来说,useRef用于引用组件的Dom节点。Vue中的ref则是引用一个vue组件。与Vue不同,react中的ref不仅仅是引用Dom节点,还可以生成一个内存不变的对象引用。 使用useState导致的空指针示例const [foo, setFoo] = useState(null);
const handler = () => {
setFoo("hello")
}
useEffect(() => {
return () => {
// 无论怎样foo都是null,给useEffect的deps加入foo也不行
if (foo === "hello") {
// do something...
}
}
}, []) 使用useRef的正确示例(解决事件处理器中对象为null的问题)const foo = useRef(null)
const handler = () => {
foo.current = "hello"
}
useEffect(() => {
return () => {
// foo.current为hello
if (foo.current === "hello") {
// do something...
}
}
}, []) useRef解决空指针问题的原因是什么?
总结起来就是:useRef生成的对象,在组件生命周期期间内存地址都是不变的。 const refContainer = useRef(initialValue); useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component. This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render. 总结一下会使用到useRef解决空指针问题的场景:
|
如何通过useReducer实现forceUpdate的效果?首先来看看useReducer的使用场景
再来看看为什么要用useReducer实现forceUpdate的效果?
如果某些情况下state没有发生变化的话,可以使用useReducer去强制重新渲染。 const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
} |
The text was updated successfully, but these errors were encountered: