react圖片檢視器外掛images-viewer-react與useRef的愛與恨
0. 緣起
啊好久沒寫博文了,一方面是沒空(換了個蘿蔔坑),另一方面是剛接觸react,有些東西也不知道嘛意思,所以邊看邊想。最近就遇到這個圖片檢視器外掛和current
不會引發元件重新渲染的事兒。
1. images-viewer-react使用要點
1.1 官網
images-viewer-react - npm (npmjs.com)
visible 可見性 noClose 去除關閉按鈕 noNavbar 消去下方導航欄(圖片縮略集) zoomable 是否放縮 rotatable 是否旋轉 scalable 是否顯示縮放按鈕 images 圖片源 defaultImg圖片載入失敗顯示的預設圖片 container inline 模式的容器(可以理解為畫框,盛放當前圖片檢視器的元素)
1.2 重點——容器
如果不設定容器,圖片檢視器就會全屏顯示,顯然這不方便使用。
import Viewer from 'images-viewer-react'; // 圖片檢視器容器 const [pictureBox, setPictureBox] = useState(); // ... {originImgVisible && ( <Modal title="原圖檢視" width={900} visible footer={null} onCancel={onCancel}> <div style={{ width: 835, height: 600, backgroundColor: '#fff', }} ref={(e) => { setPictureBox(e); }} /> {pictureBox && drawerData && ( <Viewer visible noClose noNavbar zoomable={originImgVisible} rotatable={originImgVisible} scalable={originImgVisible} images={drawerData} defaultImg={defaultImg} container={pictureBox} /> )} </Modal> )}
再繼續講這個畫框容器怎麼放的之前,來整一個新玩意兒——useRef。
2. useRef與ref
Hook API 索引 – React (reactjs.org)
請記住,當 ref 物件內容發生變化時,
useRef
並不會通知你。變更.current
屬性不會引發元件重新渲染。如果想要在 React 繫結或解綁 DOM 節點的 ref 時執行某些程式碼,則需要使用回撥 ref 來實現。
2.1 錯誤操作
我之前寫的是這樣的
const container = useRef() {container.current && drawerData && ( <Viewer visible noClose noNavbar ...
logcontainer.current
的時候一直顯示undefined
- 初始化 container: undefined
- 點選按鈕 顯示彈窗 container: null
- 點選彈窗關閉按鈕
container: <div style="width: 835px; height: 600px; background-color: rgb(255, 255, 255);"></div>
也就是說,在彈窗顯示的時候container.current
值為空,畫框區域為空,所以啥也沒顯示。
2.2 正確操作
如果使用const [pictureBox, setPictureBox] = useState()
,直接設定div
的ref
。此時效果為彈窗顯示時,e
是div
的HTML元素,彈窗關閉時,e
為null
。
3. 加入antd元件
3.1 Antdv3版本的modal報錯
react18版本不再支援unstable_renderSubtreeIntoContainer
,而antdv3中的modal
與drawer
都用到這個方法,所以有紅字報錯
ReactDOM.unstable_renderSubtreeIntoContainer() is no longer supported in React 18. Consider using a portal instead. Until you switch to the createRoot API, your app will behave as if it's running React 17.
3.2 用visible屬性值控制
useRef
的值是一直存在的
const ButtonGroup = Button.Group;
const modalOutRef = useRef()
const modalInRef = useRef()
const drawerOutRef = useRef()
const drawerInRef = useRef()
console.log('modalOutRef: ', modalOutRef, 'in', modalInRef);
console.log('drawerOutRef: ', drawerOutRef, 'in:', drawerInRef);
// ...
<ButtonGroup>
<Button onClick={() => setModalVisible(true)}>Modal</Button>
<Button onClick={() => setDrawerVisible(true)}>Drawer</Button>
</ButtonGroup>
<Modal
ref={modalOutRef}
title="Basic Modal"
visible={modalVisible}
onOk={closeWindow}
onCancel={closeWindow}
>
<p ref={modalInRef}>Some contents...</p></Modal>
<Drawer
ref={drawerOutRef}
title="Basic Drawer"
placement="right"
closable={false}
onClose={closeWindow}
visible={drawerVisible}
>
<p ref={drawerInRef}>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
3.3 用modalVisible控制組件是否渲染
{modalVisible && (<Modal
ref={modalOutRef}
title="Basic Modal"
visible
onOk={closeWindow}
onCancel={closeWindow}
>
<p ref={modalInRef}>Some contents...</p></Modal>)}
就出現了之前說過的關閉才顯示ref關聯的奇怪BUG!!!drawer元件也是同樣效果