React InstantSearch受控模式使用自定义输入组件触发最大更新深度错误
问题根因
你遇到的Maximum update depth exceeded错误,核心原因是**connectSearchBox的调用被放在了CustomSearch组件内部**:
每次CustomSearch渲染时都会生成一个全新的组件实例,React会直接卸载旧组件、挂载新组件,新组件挂载时会触发搜索状态变更,进而触发父组件Search的searchState更新、父组件重渲染,又会再次生成新的CustomSearch内部组件,最终形成无限渲染循环。
官方默认的SearchBox没有这个问题,是因为它内部的连接器初始化逻辑放在了组件外部,不会每次渲染都重建组件。
解决方案
你只要把连接器生成组件的逻辑移到组件外部,或者用useMemo缓存组件实例即可,两种实现方式都可以同时满足你「自定义搜索框」和「访问searchState判断搜索状态」的需求:
方案1:把连接器逻辑移到组件外部(更推荐)
// 组件外部只初始化一次连接器对应的组件 const ConnectedSearchBox = connectSearchBox(({ currentRefinement, refine }) => ( <input type="search" style={{ border: "1px solid black" }} value={currentRefinement} onChange={(e) => refine(e.currentTarget.value)} /> )); const CustomSearch = () => { return <ConnectedSearchBox />; }; function Search() { const [searchState, setSearchState] = React.useState({}); // 直接通过searchState.query即可判断用户是否处于搜索状态,比如: // const isSearching = !!searchState.query return ( <InstantSearch onSearchStateChange={setSearchState} searchState={searchState} searchClient={searchClient} indexName="movies" > <CustomSearch /> </InstantSearch> ); }
方案2:用useMemo缓存组件实例(适合必须把逻辑写在组件内部的场景)
const CustomSearch = () => { // 用useMemo保证只生成一次组件实例 const Component = React.useMemo(() => { return connectSearchBox(({ currentRefinement, refine }) => ( <input type="search" style={{ border: "1px solid black" }} value={currentRefinement} onChange={(e) => refine(e.currentTarget.value)} /> )); }, []); return <Component />; }; function Search() { const [searchState, setSearchState] = React.useState({}); return ( <InstantSearch onSearchStateChange={setSearchState} searchState={searchState} searchClient={searchClient} indexName="movies" > <CustomSearch /> </InstantSearch> ); }
内容的提问来源于stack exchange,提问作者aaa
相关产品推荐
相关产品推荐

