Reactjs 不断对PDF查看器组件重新加载作出反应
我在我的项目中使用了一个。我有一个可以拖动的工具Reactjs 不断对PDF查看器组件重新加载作出反应,reactjs,react-pdf,Reactjs,React Pdf,我在我的项目中使用了一个。我有一个可以拖动的工具 import React from "react"; import withStyles from "@material-ui/core/styles/withStyles"; import makeStyles from "@material-ui/core/styles/makeStyles"; import DialogContent from "@material-ui
import React from "react";
import withStyles from "@material-ui/core/styles/withStyles";
import makeStyles from "@material-ui/core/styles/makeStyles";
import DialogContent from "@material-ui/core/DialogContent";
import IconButton from "@material-ui/core/IconButton";
import ClearIcon from "@material-ui/icons/Clear";
import Draggable from "react-draggable";
import Paper from "@material-ui/core/Paper";
import Dialog from "@material-ui/core/Dialog";
import PDFViewer from "./PDFViewer";
function PaperComponent({...props}) {
return (
<Draggable
>
<Paper {...props} />
</Draggable>
);
}
const StyledDialog = withStyles({
root: {
pointerEvents: "none"
},
paper: {
pointerEvents: "auto"
},
scrollPaper: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
marginRight: 20
}
})(props => <Dialog hideBackdrop {...props} />);
const useStyles = makeStyles({
dialog: {
cursor: 'move'
},
dialogContent: {
'&:first-child': {
padding: 10,
background: 'white'
}
},
clearIcon: {
position: 'absolute',
top: -20,
right: -20,
background: 'white',
zIndex: 1,
'&:hover': {
background: 'white'
}
},
paper: {
overflowY: 'visible',
maxWidth: 'none',
maxHeight: 'none',
width: 550,
height: 730
}
});
const PDFModal = (props) => {
const classes = useStyles();
const {open, onClose, pdfURL} = props;
return (
<StyledDialog
open={open}
classes={{root: classes.dialog, paper: classes.paper}}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog"
>
<DialogContent classes={{root: classes.dialogContent}} id="draggable-dialog">
<IconButton className={classes.clearIcon} aria-label="Clear" onClick={onClose}>
<ClearIcon/>
</IconButton>
<PDFViewer
url={pdfURL}
/>
</DialogContent>
</StyledDialog>
);
};
export default PDFModal;
从“React”导入React;
从“@material ui/core/styles/withStyles”导入withStyles;
从“@material ui/core/styles/makeStyles”导入makeStyles;
从“@material ui/core/DialogContent”导入DialogContent;
从“@material ui/core/IconButton”导入图标按钮;
从“@material ui/icons/Clear”导入ClearIcon;
从“react Draggable”导入Draggable;
从“@material ui/core/Paper”导入纸张;
从“@material ui/core/Dialog”导入对话框;
从“/PDFViewer”导入PDFViewer;
函数PaperComponent({…props}){
返回(
);
}
const StyledDialog=带样式({
根目录:{
pointerEvents:“无”
},
论文:{
指针事件:“自动”
},
卷轴纸:{
显示:“flex”,
对齐项目:“居中”,
justifyContent:“柔性端”,
marginRight:20
}
})(道具=>);
const useStyles=makeStyles({
对话框:{
光标:“移动”
},
对话内容:{
“&:第一个孩子”:{
填充:10,
背景:“白色”
}
},
clearIcon:{
位置:'绝对',
前-20名,
右:-20,
背景:“白色”,
zIndex:1,
“&:悬停”:{
背景:“白色”
}
},
论文:{
溢出:“可见”,
maxWidth:“无”,
maxHeight:“无”,
宽度:550,
身高:730
}
});
常量PDFModal=(道具)=>{
const classes=useStyles();
const{open,onClose,pdfURL}=props;
返回(
);
};
导出默认PDFModal;
这是PDFViewer组件:
import React from 'react';
import { Viewer, SpecialZoomLevel, Worker } from '@react-pdf-viewer/core';
import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
import '@react-pdf-viewer/core/lib/styles/index.css';
import '@react-pdf-viewer/default-layout/lib/styles/index.css';
import ArrowForward from "@material-ui/icons/ArrowForward";
import ArrowBack from "@material-ui/icons/ArrowBack";
import Button from "@material-ui/core/Button";
import IconButton from "@material-ui/core/IconButton";
import RemoveCircleOutlineIcon from '@material-ui/icons/RemoveCircleOutline';
import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline';
import './PDFViewer.css';
const PDFViewer = ({url}) => {
const renderToolbar = (Toolbar) => (
<Toolbar>
{
(slots) => {
const {
CurrentPageLabel, CurrentScale, GoToNextPage, GoToPreviousPage, ZoomIn, ZoomOut,
} = slots;
return (
<div
style={{
alignItems: 'center',
display: 'flex',
}}
>
<div style={{ padding: '0px 2px' }}>
<ZoomOut>
{
(props) => (
<IconButton aria-label="delete" onClick={props.onClick}>
<RemoveCircleOutlineIcon />
</IconButton>
)
}
</ZoomOut>
</div>
<div style={{ padding: '0px 2px' }}>
<CurrentScale>
{
(props) => (
<span>{`${Math.round(props.scale * 100)}%`}</span>
)
}
</CurrentScale>
</div>
<div style={{ padding: '0px 2px' }}>
<ZoomIn>
{
(props) => (
<IconButton aria-label="delete" onClick={props.onClick}>
<AddCircleOutlineIcon />
</IconButton>
)
}
</ZoomIn>
</div>
<div style={{ padding: '0px 2px', marginLeft: 'auto' }}>
<GoToPreviousPage>
{
(props) => (
<Button
style={{
cursor: props.isDisabled ? 'not-allowed' : 'pointer',
height: '30px',
width: '30px'
}}
disabled={props.isDisabled}
disableElevation
disableFocusRipple
onClick={props.onClick}
variant="outlined">
<ArrowBack fontSize="small"/>
</Button>
)
}
</GoToPreviousPage>
</div>
<div style={{ padding: '0px 2px' }}>
<CurrentPageLabel>
{
(props) => (
<span>{`${props.currentPage + 1} av ${props.numberOfPages}`}</span>
)
}
</CurrentPageLabel>
</div>
<div style={{ padding: '0px 2px' }}>
<GoToNextPage>
{
(props) => (
<Button
style={{
cursor: props.isDisabled ? 'not-allowed' : 'pointer',
height: '30px',
width: '30px'
}}
disabled={props.isDisabled}
disableElevation
disableFocusRipple
onClick={props.onClick}
variant="outlined">
<ArrowForward fontSize="small"/>
</Button>
)
}
</GoToNextPage>
</div>
</div>
)
}
}
</Toolbar>
);
const defaultLayoutPluginInstance = defaultLayoutPlugin({
renderToolbar,
sidebarTabs: defaultTabs => [defaultTabs[1]]
});
// constantly called
console.log('entered')
return (
<div
style={{
height: '100%',
}}
>
<Worker workerUrl="https://unpkg.com/pdfjs-dist@2.5.207/build/pdf.worker.min.js">
<Viewer
fileUrl={url}
defaultScale={SpecialZoomLevel.PageFit}
plugins={[
defaultLayoutPluginInstance
]}
/>
</Worker>
</div>
);
};
export default PDFViewer;
从“React”导入React;
从'@react pdf Viewer/core'导入{Viewer,SpecialZoomLevel,Worker};
从'@react pdf viewer/default layout'导入{defaultLayoutPlugin};
导入“@react pdf viewer/core/lib/styles/index.css”;
导入“@react pdf viewer/default layout/lib/styles/index.css”;
从“@material ui/icons/ArrowForward”导入ArrowForward”;
从“@material ui/icons/ArrowBack”导入箭头;
从“@物料界面/核心/按钮”导入按钮;
从“@material ui/core/IconButton”导入图标按钮;
从“@material ui/icons/RemoveCircleOutline”导入RemoveCircleOutlineIcon;
从“@material ui/icons/AddCircleOutline”导入AddCircleOutlineIcon;
导入“/PDFViewer.css”;
const PDFViewer=({url})=>{
const renderToolbar=(工具栏)=>(
{
(插槽)=>{
常数{
CurrentPageLabel、CurrentScale、GoToNextPage、GoToPreviousPage、ZoomIn、ZoomOut、,
}=插槽;
返回(
{
(道具)=>(
)
}
{
(道具)=>(
{${Math.round(props.scale*100)}%`}
)
}
{
(道具)=>(
)
}
{
(道具)=>(
)
}
{
(道具)=>(
{`${props.currentPage+1}av${props.numberOfPages}`}
)
}
{
(道具)=>(
)
}
)
}
}
);
const defaultLayoutPluginInstance=defaultLayoutPlugin({
伦德托巴尔,
sidebarTabs:defaultTabs=>[defaultTabs[1]]
});
//经常打电话
console.log('entered')
返回(
);
};
导出默认PDFViewer;
我可以在控制台中看到PDFViewer不断被调用。我不确定是什么原因导致了这种重新渲染?当您将一个新的
文件URL
传递给PDFModal
时,重新渲染是否有意义?下面的顺序应该是应用程序的执行方式
PDFModal
,PDFViewer
和其他相关组件初始化PaperComponent
上下文中时,上层组件将处理该文件并作为道具传递pdfURL
工具栏
作为一个选项,因为它不使用传入的url
道具。对于重新渲染问题,我建议可以使用useCallback
包装整个PDFViewer
组件。仅当url
发生更改时才更新组件
这为何时使用useCallback
提供了一些见解,可以作为参考
const PDFViewer = useCallback(
({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
)
}, [url])
const PDFViewer=useCallback(
({url})=>{
//…跳过了代码
返回(
//…跳过了代码
)
},[url])
我会尝试在PDFViewer
之外定义你的renderToolbar
函数,看看这是否有帮助。你能提供一个codesandbox吗?@宏我在codesandbox中也尝试过同样的方法:我所能看到的是它没有频繁调用控制台.log(entered)
<代码>(仅供参考-我已将console.log(已输入)更改为console.error(已输入)在该代码沙盒中)
const PDFViewer = ({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
);
}
const PDFViewer = useCallback(
({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
)
}, [url])