afc163
2 years ago
3 changed files with 63 additions and 87 deletions
@ -1,53 +1,40 @@ |
|||
import React, { memo, useContext, useRef, useState } from 'react'; |
|||
import { fireEvent, getNodeText, render } from '../../../tests/utils'; |
|||
import React, { memo, useContext } from 'react'; |
|||
import { fireEvent, pureRender } from '../../../tests/utils'; |
|||
import Anchor from '../Anchor'; |
|||
import AnchorContext from '../context'; |
|||
|
|||
// we use'memo' here in order to only render inner component while context changed.
|
|||
const CacheInner = memo(() => { |
|||
const countRef = useRef(0); |
|||
countRef.current++; |
|||
// subscribe anchor context
|
|||
useContext(AnchorContext); |
|||
return ( |
|||
<div> |
|||
Child Rendering Count: <span id="child_count">{countRef.current}</span> |
|||
</div> |
|||
); |
|||
}); |
|||
let innerCount = 0; |
|||
let outerCount = 0; |
|||
|
|||
const CacheOuter = () => { |
|||
// We use 'useState' here in order to trigger parent component rendering.
|
|||
const [count, setCount] = useState(1); |
|||
const handleClick = () => { |
|||
setCount(count + 1); |
|||
}; |
|||
// During each rendering phase, the cached context value returned from method 'Anchor#getMemoizedContextValue' will take effect.
|
|||
// So 'CacheInner' component won't rerender.
|
|||
return ( |
|||
<div> |
|||
<button type="button" onClick={handleClick} id="parent_btn"> |
|||
Click |
|||
</button> |
|||
Parent Rendering Count: <span id="parent_count">{count}</span> |
|||
<Anchor affix={false}> |
|||
<CacheInner /> |
|||
</Anchor> |
|||
</div> |
|||
); |
|||
const handleClick = () => { |
|||
outerCount++; |
|||
}; |
|||
|
|||
it("Rendering on Anchor without changed AnchorContext won't trigger rendering on child component.", () => { |
|||
const { container } = render(<CacheOuter />); |
|||
const childCount = getNodeText(container.querySelector('#child_count')!); |
|||
// we use'memo' here in order to only render inner component while context changed.
|
|||
const CacheInner: React.FC = memo(() => { |
|||
innerCount++; |
|||
// subscribe locale context
|
|||
useContext(AnchorContext); |
|||
return null; |
|||
}); |
|||
|
|||
fireEvent.click(container.querySelector('#parent_btn')!); |
|||
const CacheOuter: React.FC = memo(() => ( |
|||
<> |
|||
<button type="button" onClick={handleClick} id="parent_btn"> |
|||
Click |
|||
</button> |
|||
<Anchor affix={false}> |
|||
<CacheInner /> |
|||
</Anchor> |
|||
</> |
|||
)); |
|||
|
|||
expect(getNodeText(container.querySelector('#parent_count')!)).toBe('2'); |
|||
// child component won't rerender
|
|||
expect(getNodeText(container.querySelector('#child_count')!)).toBe(childCount); |
|||
it("Rendering on Anchor without changed won't trigger rendering on child component.", () => { |
|||
const { container, unmount } = pureRender(<CacheOuter />); |
|||
expect(outerCount).toBe(0); |
|||
expect(innerCount).toBe(2); |
|||
fireEvent.click(container.querySelector('#parent_btn')!); |
|||
expect(getNodeText(container.querySelector('#parent_count')!)).toBe('3'); |
|||
// child component won't rerender
|
|||
expect(getNodeText(container.querySelector('#child_count')!)).toBe(childCount); |
|||
expect(outerCount).toBe(1); |
|||
expect(innerCount).toBe(2); |
|||
unmount(); |
|||
}); |
|||
|
@ -1,55 +1,42 @@ |
|||
import React, { memo, useContext, useRef, useState } from 'react'; |
|||
import React, { memo, useContext } from 'react'; |
|||
import Menu from '../index'; |
|||
import MenuContext from '../MenuContext'; |
|||
import { render, fireEvent } from '../../../tests/utils'; |
|||
import { fireEvent, pureRender } from '../../../tests/utils'; |
|||
|
|||
let innerCount = 0; |
|||
let outerCount = 0; |
|||
|
|||
const handleClick = () => { |
|||
outerCount++; |
|||
}; |
|||
|
|||
// we use'memo' here in order to only render inner component while context changed.
|
|||
const CacheInner = memo(() => { |
|||
const countRef = useRef(0); |
|||
countRef.current++; |
|||
// subscribe anchor context
|
|||
const CacheInner: React.FC = memo(() => { |
|||
innerCount++; |
|||
// subscribe locale context
|
|||
useContext(MenuContext); |
|||
return ( |
|||
<div> |
|||
Child Rendering Count: <span id="child_count">{countRef.current}</span> |
|||
</div> |
|||
); |
|||
return null; |
|||
}); |
|||
|
|||
const CacheOuter = () => { |
|||
// We use 'useState' here in order to trigger parent component rendering.
|
|||
const [count, setCount] = useState(1); |
|||
const handleClick = () => { |
|||
setCount(count + 1); |
|||
}; |
|||
// During each rendering phase, the cached context value returned from method 'Menu#getMemoizedContextValue' will take effect.
|
|||
// So 'CacheInner' component won't rerender.
|
|||
return ( |
|||
<div> |
|||
<button type="button" onClick={handleClick} id="parent_btn"> |
|||
Click |
|||
</button> |
|||
Parent Rendering Count: <span id="parent_count">{count}</span> |
|||
<Menu> |
|||
<Menu.Item key="test"> |
|||
<CacheInner /> |
|||
</Menu.Item> |
|||
</Menu> |
|||
</div> |
|||
); |
|||
}; |
|||
const CacheOuter: React.FC = memo(() => ( |
|||
<> |
|||
<button type="button" onClick={handleClick} id="parent_btn"> |
|||
Click |
|||
</button> |
|||
<Menu> |
|||
<Menu.Item key="test"> |
|||
<CacheInner /> |
|||
</Menu.Item> |
|||
</Menu> |
|||
</> |
|||
)); |
|||
|
|||
it("Rendering on Menu without changed MenuContext won't trigger rendering on child component.", () => { |
|||
const { container, unmount } = render(<CacheOuter />); |
|||
const childCount = container.querySelector('#child_count')?.textContent; |
|||
fireEvent.click(container.querySelector('#parent_btn')!); |
|||
expect(container.querySelector('#parent_count')?.textContent).toBe('2'); |
|||
// child component won't rerender
|
|||
expect(container.querySelector('#child_count')?.textContent).toBe(childCount); |
|||
const { container, unmount } = pureRender(<CacheOuter />); |
|||
expect(outerCount).toBe(0); |
|||
expect(innerCount).toBe(1); |
|||
fireEvent.click(container.querySelector('#parent_btn')!); |
|||
expect(container.querySelector('#parent_count')?.textContent).toBe('3'); |
|||
// child component won't rerender
|
|||
expect(container.querySelector('#child_count')?.textContent).toBe(childCount); |
|||
// in order to depress warning "Warning: An update to Menu inside a test was not wrapped in act(...)."
|
|||
expect(outerCount).toBe(1); |
|||
expect(innerCount).toBe(1); |
|||
unmount(); |
|||
}); |
|||
|
Loading…
Reference in new issue