如何在SolidJS中实现搜索图书信息跨页面/组件展示?
解决SolidJS中搜索图书后跨页面展示数据的问题
首先修正你代码中的核心数据存储错误:你当前用setBook(response.data)存储的是API返回的完整对象,但实际需要的图书列表是response.data.items数组。修改handleSubmit中的这一行:
setBook(response.data.items || []); // 存储图书数组,同时处理无搜索结果的情况
以下是三种可行的解决方案,根据你的页面结构选择:
方案1:Props传递(组件嵌套场景)
如果Books是SearchBooks的子组件,直接通过props传递数据:
修改SearchBooks的return部分,添加Books组件并传入数据:
return ( <div className="w-full mt-10 bg-gray-100 flex justify-center items-center"> <div className="container mx-auto dark:bg-gray-900 rounded-lg p-14"> <form onSubmit={handleSubmit}> {/* 现有表单代码 */} </form> {/* 传入图书数据给Books组件 */} <Books books={book()} /> </div> </div> );
在Books.jsx中接收并渲染数据:
function Books(props) { return ( <div className="mt-8"> <h2 className="text-2xl font-bold text-white mb-4">搜索结果</h2> {props.books.length === 0 ? ( <p className="text-white">暂无图书数据</p> ) : ( props.books.map(book => ( <div key={book.id} className="bg-white rounded-lg p-4 mb-4"> <h3 className="text-xl font-semibold">{book.volumeInfo.title}</h3> {book.volumeInfo.authors && ( <p className="text-gray-600">作者:{book.volumeInfo.authors.join(', ')}</p> )} {book.volumeInfo.categories && ( <p className="text-gray-600">类型:{book.volumeInfo.categories.join(', ')}</p> )} <p className="text-gray-600">可用性:{book.accessInfo.embeddable ? "可在线查看" : "不可在线查看"}</p> {book.volumeInfo.description && ( <p className="mt-2 text-gray-700">{book.volumeInfo.description}</p> )} </div> )) )} </div> ); } export default Books;
方案2:Solid Router导航传参(独立页面跳转场景)
如果需要跳转到全新页面展示结果,用路由状态传递数据:
- 根组件配置路由:
import { Router, Routes, Route } from "@solidjs/router"; import SearchBooks from "./SearchBooks"; import BookList from "./BookList"; function App() { return ( <Router> <Routes> <Route path="/" component={SearchBooks} /> <Route path="/book-list" component={BookList} /> </Routes> </Router> ); }
- 修改
SearchBooks,添加导航逻辑:
import axios from "axios"; import { createSignal } from "solid-js"; import { useNavigate } from "@solidjs/router"; function SearchBooks() { const [searchText, setSearchText] = createSignal(""); const navigate = useNavigate(); const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.get( `https://www.googleapis.com/books/v1/volumes?q=${searchText()}` ); const books = response.data.items || []; // 跳转并携带数据 navigate("/book-list", { state: { books } }); } catch (error) { console.log(error); } }; // 现有return代码不变 } export default SearchBooks;
- 在
BookList.jsx中获取并渲染数据:
import { useLocation } from "@solidjs/router"; function BookList() { const location = useLocation(); const books = location.state?.books || []; return ( <div className="container mx-auto mt-10 p-4"> <h2 className="text-3xl font-bold mb-6">图书搜索结果</h2> {books.length === 0 ? ( <p>暂无搜索结果</p> ) : ( books.map(book => ( <div key={book.id} className="border rounded-lg p-4 mb-4"> <h3 className="text-xl font-semibold">{book.volumeInfo.title}</h3> <p className="text-gray-600">作者:{book.volumeInfo.authors?.join(', ') || '未知'}</p> <p className="text-gray-600">类型:{book.volumeInfo.categories?.join(', ') || '未分类'}</p> <p className="text-gray-600">可用性:{book.accessInfo.embeddable ? "可在线查看" : "不可在线查看"}</p> {book.volumeInfo.description && ( <p className="mt-2 text-gray-700 line-clamp-3">{book.volumeInfo.description}</p> )} </div> )) )} </div> ); } export default BookList;
方案3:全局状态管理(多组件共享数据场景)
如果需要在多个页面共享图书数据,用createContext实现全局状态:
- 创建
BookContext.jsx:
import { createContext, useContext, createSignal } from "solid-js"; const BookContext = createContext(); export function BookProvider({ children }) { const [books, setBooks] = createSignal([]); return ( <BookContext.Provider value={{ books, setBooks }}> {children} </BookContext.Provider> ); } export function useBookContext() { return useContext(BookContext); }
- 根组件包裹全局状态:
import { Router, Routes, Route } from "@solidjs/router"; import { BookProvider } from "./BookContext"; import SearchBooks from "./SearchBooks"; import BookList from "./BookList"; function App() { return ( <BookProvider> <Router> <Routes> <Route path="/" component={SearchBooks} /> <Route path="/book-list" component={BookList} /> </Routes> </Router> </BookProvider> ); }
- 修改
SearchBooks更新全局状态:
import axios from "axios"; import { createSignal } from "solid-js"; import { useNavigate } from "@solidjs/router"; import { useBookContext } from "./BookContext"; function SearchBooks() { const [searchText, setSearchText] = createSignal(""); const navigate = useNavigate(); const { setBooks } = useBookContext(); const handleSubmit = async (e) => { e.preventDefault(); try { const response = await axios.get( `https://www.googleapis.com/books/v1/volumes?q=${searchText()}` ); const books = response.data.items || []; setBooks(books); navigate("/book-list"); } catch (error) { console.log(error); } }; // 现有return代码不变 } export default SearchBooks;
- 在
BookList.jsx读取全局状态:
import { useBookContext } from "./BookContext"; function BookList() { const { books } = useBookContext(); return ( <div className="container mx-auto mt-10 p-4"> <h2 className="text-3xl font-bold mb-6">图书搜索结果</h2> {books().length === 0 ? ( <p>暂无搜索结果</p> ) : ( books().map(book => ( <div key={book.id} className="border rounded-lg p-4 mb-4"> <h3 className="text-xl font-semibold">{book.volumeInfo.title}</h3> <p className="text-gray-600">作者:{book.volumeInfo.authors?.join(', ') || '未知'}</p> <p className="text-gray-600">类型:{book.volumeInfo.categories?.join(', ') || '未分类'}</p> <p className="text-gray-600">可用性:{book.accessInfo.embeddable ? "可在线查看" : "不可在线查看"}</p> {book.volumeInfo.description && ( <p className="mt-2 text-gray-700 line-clamp-3">{book.volumeInfo.description}</p> )} </div> )) )} </div> ); } export default BookList;
内容的提问来源于stack exchange,提问作者Hjaeter
相关产品推荐
相关产品推荐

