NextJS如何通过React Context将输入框值传递到getStaticProps
问题1:核心错误原因
- 首先,
getStaticProps是 Next.js 服务端构建/预编译阶段运行的纯服务端逻辑,完全运行在 Node.js 环境,不会访问到客户端侧的 React Context。Context 是客户端 React 运行时的状态管理机制,两者的执行生命周期完全隔离。 - 无效 Hook 报错的直接原因是你大概率在
getStaticProps内直接调用了useContext这类 React Hook。Hook 只能在 React 函数组件、自定义 Hook 的顶层调用,在服务端静态生成函数内调用 Hook 本身就违反 Hook 调用规则。 - 额外说明:哪怕替换为
getServerSideProps也无法拿到 Context 状态,服务端渲染的请求处理阶段也不存在客户端的 Context 实例。
问题2:可运行实现方案
首先明确:无法将Context中存储的搜索关键词传入getStaticProps的请求URL。getStaticProps在项目构建阶段(或者配置了增量再生的话是后台预编译阶段)就已经执行完成生成静态HTML,此时用户还没有访问页面、更没有输入搜索内容,完全不可能拿到客户端后续产生的Context状态。
可以选择以下两种适配场景的实现方案:
方案1:客户端侧请求(最适配搜索场景)
放弃用 getStaticProps 拉取搜索结果,改为在搜索结果页组件内读取 Context 存储的关键词,客户端发起请求拉取数据:
Context 定义代码
// contexts/SearchContext.js import { createContext, useContext, useState } from 'react'; const SearchContext = createContext(); export function SearchProvider({ children }) { const [searchKeyword, setSearchKeyword] = useState(''); return ( <SearchContext.Provider value={{ searchKeyword, setSearchKeyword }}> {children} </SearchContext.Provider> ); } export function useSearch() { return useContext(SearchContext); }
SearchBar 组件代码
// components/SearchBar.js import { useRouter } from 'next/router'; import { useSearch } from '../contexts/SearchContext'; export default function SearchBar() { const { setSearchKeyword } = useSearch(); const router = useRouter(); const handleSubmit = (e) => { e.preventDefault(); const keyword = e.target.searchInput.value.trim(); if (!keyword) return; setSearchKeyword(keyword); // 跳转到搜索结果页 router.push('/searchResults'); }; return ( <form onSubmit={handleSubmit}> <input name="searchInput" placeholder="输入搜索内容" /> <button type="submit">搜索</button> </form> ); }
_app.js 全局注入Provider
// pages/_app.js import { SearchProvider } from '../contexts/SearchContext'; import '../styles/globals.css'; export default function MyApp({ Component, pageProps }) { return ( <SearchProvider> <Component {...pageProps} /> </SearchProvider> ); }
搜索结果页代码
// pages/searchResults.js import { useEffect, useState } from 'react'; import { useSearch } from '../contexts/SearchContext'; export default function SearchResults() { const { searchKeyword } = useSearch(); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { if (!searchKeyword) return; // 客户端侧发起请求拉取搜索结果 const fetchResults = async () => { setLoading(true); const res = await fetch(`/api/search?keyword=${encodeURIComponent(searchKeyword)}`); const data = await res.json(); setResults(data); setLoading(false); }; fetchResults(); }, [searchKeyword]); if (loading) return <div>加载中...</div>; if (!searchKeyword) return <div>请输入搜索内容</div>; return ( <div> <h1>搜索结果:{searchKeyword}</h1> {results.map((item, idx) => ( <div key={idx}>{item.title}</div> ))} </div> ); }
方案2:URL参数传递(支持服务端拉数据)
如果需要服务端拉取搜索数据,不要用 Context 传递关键词,直接将关键词放到 URL 参数中,用 getServerSideProps 读取参数拉取数据:
调整SearchBar提交逻辑
// components/SearchBar.js 调整handleSubmit部分 const handleSubmit = (e) => { e.preventDefault(); const keyword = e.target.searchInput.value.trim(); if (!keyword) return; router.push(`/searchResults?keyword=${encodeURIComponent(keyword)}`); };
搜索结果页服务端拉取代码
// pages/searchResults.js export default function SearchResults({ results, keyword }) { return ( <div> <h1>搜索结果:{keyword}</h1> {results.map((item, idx) => ( <div key={idx}>{item.title}</div> ))} </div> ); } export async function getServerSideProps(context) { const keyword = context.query.keyword || ''; // 服务端直接发起请求拉取数据 const res = await fetch(`你的后端接口地址?keyword=${encodeURIComponent(keyword)}`); const results = await res.json(); return { props: { results, keyword } }; }
内容的提问来源于stack exchange,提问作者Ydonut13
相关产品推荐
相关产品推荐

