如何在 React.js 中将数据从子组件传递到父组件

时间:2021-02-10 08:00:12

标签: javascript reactjs react-router-dom react-component

我想将动态 pdf 文件从 BooksList 组件传递到 react-router-domLink 组件> 这样当我点击 Link 中的 BooksList 组件时,一个 pdf 文件将被传递到 Link,然后 Link > 将此 pdf 文件转发到 PDFViewer 组件,在该组件中将呈现此 pdf 文件。如果不可能,请建议我可以用来实现此功能的方法。传递任何数据之前的代码示例如下:

<Link to="/pdf_viewer">
    <BooksList></BooksList>
</Link>

<Route path="/pdf_viewer">
    <PDFViewer></PDFViewer>
</Route>

图书列表

export class BooksList extends Component {
    render() {
        return this.props.books.map((book)=> (
          //Here there is book info rendered from props
          //PDF file is an attribute in book eg. book.pdf_file
          <div>Title: {book.book_title}</div>
        ));
    }
}

export default BooksList

PDF查看器

export class PDFViewer extends Component {
    
    constructor(props){
        super(props);
        const { state: { pdfFile } } = this.props.location;
    }

    render() {
        return (
            <div key={book._id} className="pdfViewer">
                <embed src={ `data:application/pdf;base64, ${this.state}` } width="100%" height="600px"></embed>
            </div>
        )
    }

}

export default PDFViewer

未链接的图书列表

export class UnLinkedBooksList extends Component {
    viewPDFHandler = pdfFile => {
        const {history} = this.props;
        history.push({
            pathname: "/pdfviewer",
            state: {
                pdfFile
            }
        });
    }
    render() {
        return this.props.books.map((book)=> (
            <div>
                <button type="button" onClick={()=> this.viewPDFHandler(book.pdf_file_byte["$binary"])}>View PDF</button>
            </div>
        ));
    }
}

const BooksList = withRouter(UnLinkedBooksList);

export default UnLinkedBooksList

应用

export class App extends Component {

  state = {
    books: []
  }

  componentDidMount(){
    axios.get("http://127.0.0.1:5000/get_all_books").then(res=>this.setState({books:res.data.all_books}))
  }
  render() {
    return (
      <Router>
        {/* Index Page */}
        <Route exact path="/">
          <div className="App">
            <SearchBar></SearchBar>
            <div className="row p-10">
              <div className="col-lg-6">
                <Link to="/pdf_viewer" className="text-decoration-none">
                  <BooksList books={this.state.books}></BooksList>
                </Link>
              </div>
            </div>        
          </div>
        </Route>

        {/* PDF Viewer Page */}
        <Route path="/pdf_viewer" className="text-decoration-none">
          <PDFViewer></PDFViewer>
        </Route>

       </Router>
    )
  }
}

export default App

2 个答案:

答案 0 :(得分:1)

history 中的路由上下文公开 BooksList 对象,并为每个映射的书籍添加一个处理程序,以将 PDF 文件引用作为路由转换负载传递。由于 BooksList 是基于类的组件并且不是由 Roiute 呈现(它可能应该是,顺便说一句),请使用 withRouter 高阶组件装饰和注入 route props, (history, location, match).

class UnlinkedBooksList extends Component {
  viewPdfHandler = pdfFile => {
    const { history } = this.props;
    history.push({
      pathname: "/pdf_viewer",
      state: {
        pdfFile
      }
    });
  };

  render() {
    return this.props.books.map((book)=> (
      //Here there is book info rendered from props
      //PDF file is an attribute in book eg. book.pdf_file
      ...
      <button
        type="button"
        onClick={() => viewPdfHandler(book.pdf_file)}
      >
        View PDF
      </button>
    ));
  }
}

const BooksList = withRouter(UnlinkedBooksList);

export default BooksList;

在应用中,默认导入 BooksList,这是将具有 location 属性的链接组件。

import BooksList from './path/to/BooksList';

在接收端,您可以提取路由状态。在 PDFView 道具上渲染 component 以便它也接收路线道具,特别是 location 以便它可以访问路线状态。

<Route path="/pdf_viewer" component={PDFViewer} />

在 PDFViewer 中,从 pdfFile 对象访问 location

const { state: { pdfFile } } = this.props.location;

答案 1 :(得分:0)

您可以执行以下操作;

(*
3.1 A time of day can be represented as a 
triple (hours, minutes, f) 
where f is either AM or PM – or as a record. 

Declare a function to test whether one time of day comes 
before another. 

For example, (11,59,"AM") comes before (1,15,"PM"). 

Make solutions with triples as well as with records. 

Declare the functions in infix notation.

Hansen, Michael R.; Rischel, Hans. 
Functional Programming Using F# (p. 66). 
Cambridge University Press. Kindle Edition. 
*)

type TimeOfDayTriple = int * int * string

let (<.) ((hour1, min1, pod1):TimeOfDayTriple) ((hour2, min2, pod2):TimeOfDayTriple) =
    true
//val ( <. ) : int * int * string -> int * int * string -> bool

let (<.) ((hour1, min1, pod1):TimeOfDayTriple) ((hour2, min2, pod2):TimeOfDayTriple) =
    (pod1, pod2)
//val ( <. ) : int * int * string -> int * int * string -> string * string

let (<.) ((hour1, min1, pod1):TimeOfDayTriple) ((hour2, min2, pod2):TimeOfDayTriple) =
    pod1 + pod2
val ( <. ) : int * int * string -> int * int * string -> string
    
let (<.) ((hour1, min1, pod1):TimeOfDayTriple) ((hour2, min2, pod2):TimeOfDayTriple) =
    pod1 < pod2;;
//Ch03.fsx(32,5): error FS0001: This expression was expected to have type
//    'int * int * string'    
//but here has type
//    'string'    

在您的 Booklist 组件上,

...
const [url, setURL] = useState("");
const setPDFurl = (link)=>{
   setURL(link);
}
<Link to={`/pdf_viewer/${url}`}>
  <BooksList getURL = {setPDFurl }></BooksList>
</Link>
...

希望它是有道理的。