1. 程式人生 > 其它 >react圖片檢視器外掛images-viewer-react與useRef的愛與恨

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

  1. 初始化 container: undefined
  2. 點選按鈕 顯示彈窗 container: null
  3. 點選彈窗關閉按鈕
container:  <div style=​"width:​ 835px;​ height:​ 600px;​ background-color:​ rgb(255, 255, 255)​;​">​</div>​

也就是說,在彈窗顯示的時候container.current值為空,畫框區域為空,所以啥也沒顯示。

2.2 正確操作

如果使用const [pictureBox, setPictureBox] = useState(),直接設定divref。此時效果為彈窗顯示時,ediv的HTML元素,彈窗關閉時,enull

3. 加入antd元件

3.1 Antdv3版本的modal報錯

react18版本不再支援unstable_renderSubtreeIntoContainer,而antdv3中的modaldrawer都用到這個方法,所以有紅字報錯

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元件也是同樣效果