child 组件中未定义 react prop
react prop is undefined in child component
Main.js
import axios from 'axios'
import React, { Component, useEffect, useState } from 'react'
import { BrowserRouter as Router, Switch, Route} from "react-router-dom";
import Books from './Books'
import Navbar from './Navbar'
import AddBook from './AddBook';
import BookDetail from './BookDetail';
const Main = () => {
let [selectedBook, setSelectedBook] = useState() // Storing the data from Books.js
let [books, setBooks] = useState([])
useEffect(() => {
axios.get('http://127.0.0.1:8000/api/get-books')
.then(res => {
setBooks(books = res.data)
})
})
return (
<Router>
<div>
<Navbar title={selectedBook}/> // is defined here <----
<div className='container'>
<Switch>
<Route exact path='/' >
<Books books={books} onBookSelect={(book) => {setSelectedBook(book)} }/> // Receiving the data from here
</Route>
<Route path='/add-book' >
<AddBook />
</Route>
<Route path={`/details`} >
<BookDetail bookId={selectedBook} /> // is undefined when passed here <----
</Route>
</Switch>
</div>
</div>
</Router>
)
}
export default Main
Books.js
import React, { Component, useState } from 'react'
import BookDetail from './BookDetail'
const Books = ({books, onBookSelect}) => {
const sendBookId = e => {
let bookId = e.target.value
onBookSelect('i am not undefined') // sending the data to Main.js
setTimeout(function(){ window.location.href='http://localhost:3000/details' }, 10)
}
return (
<div>
<div className='books'>
{books.map(book => (
<div className='book'>
<h2>{book.name}</h2>
<p>Author: <a href='#'>{book.author}</a></p>
<button className="btn" value={book.id} onClick={sendBookId}>View Details</button> // Getting the id from here
</div>
))}
</div>
</div>
)
}
export default Books
BookDetail.js
import React, { useEffect } from 'react'
import axios from 'axios'
import { useState } from 'react'
const BookDetail = ({bookId}) => {
return (
<div>
<p>book: {bookId}</p> // bookId is undefined
</div>
)
}
export default BookDetail
样本来自 localhost:8000/api/get-books
{
"id": 5,
"name": "Book1",
"author": "Author1",
"content": "a normal book",
"isbn": "235456",
"passcode": "123",
"created_at": "2021-07-12T16:29:47.114356Z",
"pages": "3"
}
基本上,数据从Book.js发送到Main.js的parent组件,存储在selectedBook中,定义数据并显示在标题中,但是当我将它添加为道具并尝试从那里访问它时,它变得不确定,我做错了什么?
问题
感谢 Yoshi 首先指出,但您从主页导航到图书详细信息页面的方式存在问题。改变 window.location.href
对象实际上会重新加载页面和您的应用程序。由于 React 状态存在于内存中,因此它会在页面重新加载时丢失。
解决方案
使用 Router
上下文提供的 history
对象推送到新路由。由于您已经在使用功能组件,因此您可以从 react-router-dom
导入 useHistory
React 挂钩并发出命令式导航。
import { useHistory } from 'react-router-dom';
...
const Books = ({ books, onBookSelect }) => {
const history = useHistory(); // <-- access the history object from hook
const sendBookId = (e) => {
const bookId = e.target.value;
onBookSelect(bookId);
history.push("/details"); // <-- issue PUSH to route
};
return (
<div>
<div className="books">
Books
{books.map((book) => (
<div className="book">
<h2>{book.name}</h2>
<p>
Author: <a href="#">{book.author}</a>
</p>
<button className="btn" value={book.id} onClick={sendBookId}>
View Details
</button>
</div>
))}
</div>
</div>
);
};
Main.js
import axios from 'axios'
import React, { Component, useEffect, useState } from 'react'
import { BrowserRouter as Router, Switch, Route} from "react-router-dom";
import Books from './Books'
import Navbar from './Navbar'
import AddBook from './AddBook';
import BookDetail from './BookDetail';
const Main = () => {
let [selectedBook, setSelectedBook] = useState() // Storing the data from Books.js
let [books, setBooks] = useState([])
useEffect(() => {
axios.get('http://127.0.0.1:8000/api/get-books')
.then(res => {
setBooks(books = res.data)
})
})
return (
<Router>
<div>
<Navbar title={selectedBook}/> // is defined here <----
<div className='container'>
<Switch>
<Route exact path='/' >
<Books books={books} onBookSelect={(book) => {setSelectedBook(book)} }/> // Receiving the data from here
</Route>
<Route path='/add-book' >
<AddBook />
</Route>
<Route path={`/details`} >
<BookDetail bookId={selectedBook} /> // is undefined when passed here <----
</Route>
</Switch>
</div>
</div>
</Router>
)
}
export default Main
Books.js
import React, { Component, useState } from 'react'
import BookDetail from './BookDetail'
const Books = ({books, onBookSelect}) => {
const sendBookId = e => {
let bookId = e.target.value
onBookSelect('i am not undefined') // sending the data to Main.js
setTimeout(function(){ window.location.href='http://localhost:3000/details' }, 10)
}
return (
<div>
<div className='books'>
{books.map(book => (
<div className='book'>
<h2>{book.name}</h2>
<p>Author: <a href='#'>{book.author}</a></p>
<button className="btn" value={book.id} onClick={sendBookId}>View Details</button> // Getting the id from here
</div>
))}
</div>
</div>
)
}
export default Books
BookDetail.js
import React, { useEffect } from 'react'
import axios from 'axios'
import { useState } from 'react'
const BookDetail = ({bookId}) => {
return (
<div>
<p>book: {bookId}</p> // bookId is undefined
</div>
)
}
export default BookDetail
样本来自 localhost:8000/api/get-books
{
"id": 5,
"name": "Book1",
"author": "Author1",
"content": "a normal book",
"isbn": "235456",
"passcode": "123",
"created_at": "2021-07-12T16:29:47.114356Z",
"pages": "3"
}
基本上,数据从Book.js发送到Main.js的parent组件,存储在selectedBook中,定义数据并显示在标题中,但是当我将它添加为道具并尝试从那里访问它时,它变得不确定,我做错了什么?
问题
感谢 Yoshi 首先指出,但您从主页导航到图书详细信息页面的方式存在问题。改变 window.location.href
对象实际上会重新加载页面和您的应用程序。由于 React 状态存在于内存中,因此它会在页面重新加载时丢失。
解决方案
使用 Router
上下文提供的 history
对象推送到新路由。由于您已经在使用功能组件,因此您可以从 react-router-dom
导入 useHistory
React 挂钩并发出命令式导航。
import { useHistory } from 'react-router-dom';
...
const Books = ({ books, onBookSelect }) => {
const history = useHistory(); // <-- access the history object from hook
const sendBookId = (e) => {
const bookId = e.target.value;
onBookSelect(bookId);
history.push("/details"); // <-- issue PUSH to route
};
return (
<div>
<div className="books">
Books
{books.map((book) => (
<div className="book">
<h2>{book.name}</h2>
<p>
Author: <a href="#">{book.author}</a>
</p>
<button className="btn" value={book.id} onClick={sendBookId}>
View Details
</button>
</div>
))}
</div>
</div>
);
};