Mar*_*rco 13 reactjs react-pdf
我在我的项目中使用React PDF 查看器。我有一个react mui 对话框组件,我使用 react draggable 来拖动它。
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;
Run Code Online (Sandbox Code Playgroud)
这是 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;
Run Code Online (Sandbox Code Playgroud)
我可以在控制台中看到不断调用 PDFViewer。我不确定是什么导致了一直重新渲染?
fileUrl当您有新的传递 to时,重新渲染不是有意义吗PDFModal?以下顺序应该是应用程序的执行方式。
PDFModal,PDFViewer以及其他相关组件初始化PaperComponent,上层组件会处理它并pdfURL作为 props传递const PDFModal = (props) => {
const { ......., pdfURL } = props;
//...skipped code
return (
<StyledDialog
PaperComponent={PaperComponent}
>
//...skipped code
<PDFViewer
url={pdfURL}
/>
</StyledDialog>
);
};
Run Code Online (Sandbox Code Playgroud)
PDFViewer更新了,因为有一个新道具。const PDFViewer = ({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
);
}
Run Code Online (Sandbox Code Playgroud)
我同意 @LindaPaiste 所说的,Toolbar也许可以添加一个选项,因为它不使用url传入的 props。对于重新渲染问题,我建议useCallback可以使用它来包装整个PDFViewer组件。仅当 发生更改时才更新组件url。
此链接提供了一些有关何时使用的见解,useCallback可以作为参考。
const PDFViewer = useCallback(
({ url }) => {
//...skipped code
return (
//...skipped code
<Viewer
fileUrl={url}
/>
)
}, [url])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
551 次 |
| 最近记录: |