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组件也是同样效果