Reputation: 8297
First of all, I am not using React-Redux
. I know it would help, but it would take too long for my team to make a transition. So, please understand that I need a solution without React-Redux
.
What I am trying to do is, I am building a PDF extractor. I want a user to select a page of a PDF that he/she wants to extract.
I have a component called PDFViewer
which does the rendering work.
PDFViewer
renderPdf() {
const {pdf, pageNo} = this.state
const container = document.getElementById('container')
if(this.props.selectedPage){
console.log('selectedPage exists', this.props.selectedPage)
pdf.getPage(this.props.selectedPage).then((page) => {
const scale = this.calcScale(page)
const viewport = page.getViewport(scale)
const div = document.createElement('div')
// Set id attribute with page-#{pdf_page_number} format
div.setAttribute('id', `page-${(page.pageIndex + 1)}`)
div.style.width = `${viewport.width}px`
div.style.height = `${viewport.height}px`
page
.getOperatorList()
.then((opList) => {
const svgGfx = new window.PDFJS.SVGGraphics(
page.commonObjs,
page.objs
)
return svgGfx.getSVG(opList, viewport)
})
.then((svg) => {
// If there's already rendered page, delete it.
if (container.childNodes.length > 0) {
container.removeChild(container.childNodes[0])
}
container.appendChild(svg)
return svg
})
})
} else {
console.log('props', this.props)
pdf.getPage(pageNo).then((page) => {
const scale = this.calcScale(page)
const viewport = page.getViewport(scale)
const div = document.createElement('div')
// Set id attribute with page-#{pdf_page_number} format
div.setAttribute('id', `page-${(page.pageIndex + 1)}`)
div.style.width = `${viewport.width}px`
div.style.height = `${viewport.height}px`
page
.getOperatorList()
.then((opList) => {
const svgGfx = new window.PDFJS.SVGGraphics(
page.commonObjs,
page.objs
)
return svgGfx.getSVG(opList, viewport)
})
.then((svg) => {
// If there's already rendered page, delete it.
if (container.childNodes.length > 0) {
container.removeChild(container.childNodes[0])
}
container.appendChild(svg)
return svg
})
})
}
}
render() {
const {pdf, pageNo} = this.state
const {showPagination} = this.props
return (
<div>
{showPagination && (
<PageTurner
nextPage={this.nextPage}
previousPage={this.previousPage}
pageNo={pageNo}
numPages={pdf ? pdf.numPages : 0}
/>
)}
<div id="container" />
</div>
)
The PageTurner
in render just makes the user selects the page that one wants to render. renderPdf()
is in charge of rendering it.
NextComponent
render() {
const tableStyle = this.getTableStyle();
const tableSettings = this.getTableSettings();
return (
<div>
{//<ReferenceMenu />
}
<div
style={sideBySide}>
<PDFViewer
paginationCallback={this.handlePageChange}
pdfData={this.state.pdfData}
desiredWidth={600}
selectedPage={2}
/>
<TablePosition
style={tables}
step={this.props.step}
pdfData={this.props.pdfData}
tableSettings={tableSettings}
tableStyle={tableStyle}
fileName={this.state.fileName}
tableSize={this.getTableSize()}
tableOffset={this.state.tableOffset}
desiredWidth={700}
updateXOffset={x => this.updateXOffset(x)}
updateYOffset={y => this.updateYOffset(y)}
markTable={() => this.markTable()}
setOutputLabels={(row, col, val) => this.setOuputLabels(row, col, val)}
/>
</div>
</div>
);
}
In my next component, it tries to render the page of the selected PDF page and align with the table that the PDF page has (the table part is not important in this question).
As you can see, I sent selectedPage={2}
as a prop to the PDFViewer
and this successfully renders the 2nd page of the PDF. But the value is hard coded.
My question is, how can I fetch the page number selected in PDFViewer
(this.state.pageNo
in PDFViewer
) and use it in the selectedPage={ HERE }
?
Please help
Upvotes: 0
Views: 88
Reputation: 2390
I took my simple example from the comments and substituted in your component names to give you a better idea of how to lift the state up the component tree. I tried to base the flow on what I could gather from the context of your problem. Again, I would recommend reading React's article Lifting State Up.
const PageTurner = ({ onConfirm, onPageChange, pageNo }) => (
<div>
<button type="button" onClick={() => onPageChange(pageNo - 1)}>
Prev ({pageNo - 1})
</button>
<button type="button" onClick={() => onPageChange(pageNo + 1)}>
Next ({pageNo + 1})
</button>
<button type="button" onClick={onConfirm}>
Confirm
</button>
</div>
);
const PdfViewer = ({ pageNo }) => (
<div>
<h1>PdfViewer</h1>
<h2>Current Page is {pageNo}</h2>
</div>
);
const Step1 = ({ onConfirm, onPageChange, pageNo }) => (
<div>
<PdfViewer pageNo={pageNo} />
<PageTurner
onConfirm={onConfirm}
onPageChange={onPageChange}
pageNo={pageNo}
/>
</div>
);
const NextComponent = ({ pageNo }) => (
<div>
<h1>NextComponent</h1>
<label>Page number is {pageNo}</label>
</div>
);
class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
pageNo: 1,
step: 1
};
this.handleConfirm = this.handleConfirm.bind(this);
this.handlePageChange = this.handlePageChange.bind(this);
}
handleConfirm() {
this.setState({
step: 2
});
}
handlePageChange(pageNo) {
this.setState(state => ({
pageNo
}));
}
render() {
const { pageNo, step } = this.state;
return (
<div>
{step === 1 && (
<Step1
onConfirm={this.handleConfirm}
onPageChange={this.handlePageChange}
pageNo={pageNo}
/>
)}
{step === 2 && <NextComponent pageNo={pageNo} />}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Upvotes: 1