我们如何从正在使用的组件中获取道具? (反应)

时间:2018-06-28 01:26:05

标签: javascript reactjs

首先,我没有使用React-Redux。我知道这会有所帮助,但是我的团队过渡需要很长时间。因此,请理解,我需要一个没有React-Redux的解决方案。

我想做的是,我正在构建PDF提取器。我希望用户选择他/她要提取的PDF页面。

我有一个名为PDFViewer的组件,可以完成渲染工作。

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>
    )

渲染中的PageTurner仅使用户选择一个要渲染的页面。 renderPdf()负责呈现它。

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>
    );
}

在我的下一个组件中,它尝试呈现所选PDF页面的页面并与PDF页面具有的表对齐(表部分在此问题中并不重要)。

如您所见,我将selectedPage={2}作为道具发送到PDFViewer,这成功呈现了PDF的第二页。但是该值是硬编码的。

我的问题是,如何获取在PDFViewer中选择的页码(在this.state.pageNo中的PDFViewer中)并在selectedPage={ HERE }中使用它?

请帮助

1 个答案:

答案 0 :(得分:1)

我从注释中提取了一个简单的示例,并替换了您的组件名称,以使您更好地了解如何将状态提升到组件树。我试图根据从问题的背景中可以收集到的信息来确定流程。同样,我建议阅读React的文章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>