lijianan
2 years ago
committed by
GitHub
1 changed files with 30 additions and 43 deletions
@ -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> |
|||
const CacheOuter: React.FC = memo(() => ( |
|||
<> |
|||
<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> |
|||
); |
|||
}; |
|||
</> |
|||
)); |
|||
|
|||
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