今日文章目录
- 前言
- useMemo()
- 实作纪录
- 参考资料
- 後续
今天要练习 useMemo()
,不过爬了很多文,觉得还无法好好消化,这篇主要纪录一些我找到的资料笔记,还有练习的过程。开始吧!
昨天我们在切换页面的时候,透过Provider
value props把{state, setState}
传下去,让子层可以改值。
// Provider 传值与方法:
function App() {
const [themsState, setThemeState] = useState(theme.light);
return (
<ThemeContext.Provider value={{ themsState, setThemeState }}>
...
</ThemeContext.Provider>
);
}
export default App;
function CategoryList(props) {
const { themsState, setThemeState } = useContext(ThemeContext);
return (...)
}
console.log()
看一下,会发现:Provider
传什麽,useContext()
就会回传什麽(就是最新值)。
官方文件有提到以下情况:
我想确定目前写法:<Context.Provider value ={{state, setState}}></Context.Provider>
会不会造成上述的问题。搜了一轮资料,决定用useMemo inside Context API - React的方法来测试看看。
为了做个测试,我分别在父层ToDoPage
,子层CategoryList
TodoList
component内加入 console.log()
,来确认一下使用useMemo()
与没有使用useMemo()
的差异。
ToDoPage
点击按钮更新值时,Provider props value 是否会重新建立,导致子层 CategoryList
ToDoList
re-render?CategoryList
父层加入 ThemeContext.Provider
value props :useMemo()
,当 dependency改变时,才更新回传值。ToDoList
父层加入 ThemeContext.Provider
value props :{ themsState, setThemeState }
export default function ToDoPage() {
const [forceRender, setForceRender] = useState(false);
const [themsState, setThemeState] = useState(theme.light);
const themeContextProvider = useMemo(() => (
{ themsState, setThemeState }), [themsState, setThemeState]
);
return (
<>
{console.log('hey! I am in ToDoPage.')}
<MainLayout
menu={(
<ThemeContext.Provider value={themeContextProvider}>
<CategoryList />
</ThemeContext.Provider>
)}
content={(
<ThemeContext.Provider value={{ themsState, setThemeState }}>
<ToDoList />
</ThemeContext.Provider>
)}
/>
<Button onClick={() => setForceRender(!forceRender)}>Rerender Parent</Button>
</>
);
}
显示效果:
ToDoList
或 CategoryList
切换 theme
,更新ThemeContext.Provider
值。
ToDoPage
点击按钮: 触发 ToDoPage
CategoryList
ToDoList
re-render。
疑?看不出来 useMemo()
的效果
export default memo(CategoryList);
export default memo(ToDoList);
显示效果:
ToDoList
或 CategoryList
切换 theme
,更新ThemeContext.Provider
值。
ToDoPage
点击按钮: 触发 ToDoPage
ToDoList
re-render。CategoryList
没有。
呼~终於有点收获...
目前看起来的状况:
测试A:父层状态改变,子层re-render。
测试B:父层状态改变,透过memo()
比对CategoryList
ToDoList
,根本没有props
,所以不受父层状态改变影响,唯一带来改变的是ToDoList
的ThemeContext.Provider value={{ themsState, setThemeState }}
,每次都重新建立。
不过我应该把 console.log() 放一个在 useMemo()
比较准才对..
useMemo 小百科:
useMemo(() => computeExpensiveValue(a, b), [a, b]);
- 为了解决当元件本身改变状态 re-render,避免元件内无关的逻辑重复渲染的效能问题。
- 用途:当dependency改变,才会执行
computeExpensiveValue(a, b)
重新计算,回传一个 memoized 的值。- 参数:
computeExpensiveValue(a, b)
: 一function,回传值会让React记着,在dependency没改变的情况下,会一直沿用该回传值。[a, b]
: dependency。
memo 小百科:
memo(MyComponent, areEqual)
:
React 渲染机制,只要父层state
改变,不论子层接收的props
值是否有改变,子层一律强迫 re-render。
memo()
是为了解决子层接收的props
导致重复渲染的效能问题。
- 用途:比对 更新前後
props
差异,没有改变,会跳过这次 re-render。- 参数:
>MyComponent
: 作用元件
>areEqual *(optional)*
: 客制function。memo()
比对方式shallowly compare complex objects in the props object
,如果要做更深层的比对,可以自己写。- If your function component wrapped in React.memo has a useState, useReducer or useContext Hook in its implementation, it will still rerender when state or context change. - 节录React 官网。
Object.is(value1, value2)
React uses the
Object.is comparison algorithm
.
哇~真的把30天撑完了,好感动喔
10天React练习让我有机会重新再回来看React 文件,我记得我刚开始接触的时候,真的是有看没有懂...目前写了半年多,回来看文件会发现以前看不懂的,现在渐渐能理解它的意思,还有很多需要再练习,但觉得满足。感谢铁人赛!
这10天只有写到一小部分,回头看自己的文章,有些知识漏洞。之後会继续补齐 use系列,不会一天一po,等我练到有点心得再继续跟大家分享,恭喜各位铁人完赛,下次见罗!
<<: 【後转前要多久】# Day15 CSS -难东西 (伪元素)
>>: # Day 21 Heterogeneous Memory Management (HMM) (一)
昨天已经学会要如何呼叫套件了,今天就让我们来学习套件里的语法运用吧! 首先先呼叫我们的NumPy套件...
join 利用栏位的关联性,将不同的资料表串连起来。 students 资料表 s_id name ...
高级技术架构师 Frederic Lhoest 在网上发现了指导视频和案例研究,这些信息和案例研究...
Starts fast, stays fast Web App 的效能会直接影响使用者体验,也会影响...
activity_main: 在LinearLayout中加入播放/暂停、停止、循环的按钮 <...