问题描述
我正在阿尔戈利亚建立一个过滤器Modal。在该过滤器模式上,我有一个标准的优化列表(请参见下面的代码)。当用户在模式上单击“搜索”时,优化列表值将丢失(即未应用于我的组件),但是没有有关如何存储优化列表输出的指南。
我想要的是本质上使我的优化列表值在我关闭模式时不会清除。
refinementlist.js
import React from 'react';
import { RefinementList } from 'react-instantsearch-dom';
const toRefine = () => {
return (
<div>
<RefinementList
attribute={`tags`}
searchable
limit={5}
/>
</div>
);
};
export default toRefine;
filter.js
import React from 'react';
import toRefine from './toRefine';
const Filters = () => {
return (
<div>
<toRefine />
</div>
);
};
export default Filters;
MainPage.js
import React,{ useState } from 'react';
import Hits from './hits';
import algoliasearch from 'algoliasearch/lite';
import { InstantSearch } from 'react-instantsearch-dom';
import Modal from 'react-modal';
import Filters from './filters';
Modal.setAppElement('#root');
const searchC = algoliasearch($ENV_VARS);
const Page = () => {
const [ modalIsOpen,setIsOpen ] = useState(false); //Hook for modal
function openModal() {
setIsOpen(true);
}
function closeModal() {
setIsOpen(false);
}
return (
<div>
<InstantSearch
indexName="index"
searchClient={searchC}
>
<CustomSearchBox />
<button onClick={openModal}>Show FILTERS</button>
<Configure hitsPerPage={20} />
<Hits />
<Modal
isOpen={modalIsOpen}
onRequestClose={closeModal}
contentLabel="filterElement"
className={styles.modal}
overlayClassName={styles.overlay}
>
<FilterPage />
</Modal>
</InstantSearch>
</div>
);
};
export default Page;
解决方法
每个React InstantSearch小部件负责其UI状态,需要挂载。我不熟悉react-modal
,但是从我收集的文档中可以了解,模态实例在关闭时被销毁,而不是隐藏,因此RefinementList
也被卸载。
您可以采取的措施来避免这种行为,即只要关闭窗口小部件时就手动更改窗口小部件的状态(关闭模式时除外),并将其作为默认优化注入到窗口小部件中。
function App() {
const [brandState,setBrandState] = React.useState([]);
// ...
return (
<InstantSearch
onSearchStateChange={(state) => {
if (modalIsOpen && state.refinementList?.brand) {
setBrandState(state.refinementList.brand);
}
}}
>
<Modal isOpen={modalIsOpen}>
<RefinementList
defaultRefinement={brandState}
attribute="brand"
/>
</Modal>
</InstantSearch>
);
}
您始终需要在应用程序中安装RefinementList
,以便该状态保持在React InstantSearch的内部状态。您可以通过使用connectRefinementList
连接器创建一个虚拟的优化列表来声明性地执行此操作,该列表不会呈现任何内容。
import { connectRefinementList } from 'react-instantsearch-dom';
// ...
const VirtualRefinementList = connectRefinementList(() => null);
function App() {
// ...
return (
<InstantSearch
onSearchStateChange={(state) => {
if (modalIsOpen && state.refinementList?.brand) {
setBrandState(state.refinementList.brand);
}
}}
>
<VirtualRefinementList defaultRefinement={brandState} attribute="brand" />
{/* ... */}
</InstantSearch>
);
}
您可以在此CodeSandbox demo上看到它的运行情况。