Использование текущего состояния и совместная работа фильтров
Я смог заставить выпадающий список из моего предыдущего вопроса работать, однако теперь у меня проблема, когда мои два фильтра не работают вместе. Например, если я отфильтрую по городу (Манхэттен), а затем выберу рынок (Домовладельцы), я ожидаю получить список всех домовладельцев в Манхэттене. Вместо этого я получаю либо только список результатов в Манхэттене, либо список для домовладельцев. Я предполагаю, что это может быть связано с другой моей проблемой: когда я выбираю "Все", я получаю не все результаты, а вместо этого ничего не происходит.
Вот моя настройка - у меня есть страница статей, где отображаются все статьи. Я использую sortedList, чтобы сохранить исходный список:
const FullList = () => {
...
<div className="all-entries-center">
{state.sortedList.map((e) => (
<Entry key={e.id} entry={e} />
))}
</div>
Затем страница управления фильтрами, где я настраиваю раскрывающийся список:
function Controls() {
const [state, setState] = useContext(StateContext);
const { list, market, region } = state;
// get all unique values
const getUnique = (items, value) => {
return [...new Set(items.map((item) => item[value]))];
};
let regions = getUnique(list, "region");
// add all
regions = ["All", ...regions];
// map to jsx
regions = regions.map((item, index) => {
return (
<option value={item} key={index}>
{item}
</option>
);
});
let markets = getUnique(list, "market");
// add all
markets = ["All", ...markets];
// map to jsx
markets = markets.map((item, index) => {
return (
<option value={item} key={index}>
{item}
</option>
);
});
...
<select
name="region"
id="region"
value={region}
className="form-control drop-down"
onChange={(event) =>
setState({ [event.target.name]: event.target.value })
}
>
{regions}
</select>
...
<select
name="market"
id="market"
value={market}
className="form-control drop-down"
onChange={(event) =>
setState({ [event.target.name]: event.target.value })
}
>
{markets}
</select>
Наконец, мой контекст:
const StateContext = createContext([{}, () => {}]);
const reducer = (prevState, updatedProperty) => ({
...prevState,
...updatedProperty,
});
let allEntries = formatData(articles);
let featuredEntries = allEntries.filter((e) => e.featured === true);
let percentageOffMax = Math.max(
...allEntries.map((item) => item.percentageOff)
);
let avgppMax = Math.max(...allEntries.map((item) => item.avgpp));
function formatData(items) {
let tempItems = items.map((e) => {
let id = e.id;
let images = e.images;
let singleEntry = { ...e, images, id };
return singleEntry;
});
return tempItems.sort((a, b) => a.avgpp - b.avgpp);
}
const initState = {
list: allEntries,
sortedList: allEntries,
featuredEntries: featuredEntries,
percentageOffMax,
avgppMax,
market: "All",
region: "All",
};
// Create a provider for components to consume and subscribe to changes
const StateProvider = (props) => {
const [state, setState] = useReducer(reducer, initState);
let market = state.market;
let region = state.region;
const didMountRef = useRef(false);
let tempList = state.list;
useEffect(() => {
// REGION ALREADY SET
if (region !== "All" && didMountRef.current) {
// DO SOMETHING AFTER REGION HAS BEEN SET
let tempListItems = tempList.filter((e) => e.region === region);
setState({ sortedList: tempListItems });
} else {
let tempList = state;
let tempListItems = tempList.list.filter(
(e) => e.market === "Homeowners" || e.market === "Renters"
);
setState({ sortedList: tempListItems });
didMountRef.current = true;
}
}, [region]);
useEffect(() => {
// MARKET ALREADY SET
if (region !== "All" && didMountRef.current) {
// DO SOMETHING AFTER MARKET HAS BEEN SET
// let tempList = state.list;
let tempListItems = tempList.filter((e) => e.market === market);
setState({ sortedList: tempListItems });
} else {
let tempList = state;
let tempListItems = tempList.list.filter(
(e) => e.market === "Homeowners" || e.market === "Renters"
);
setState({ sortedList: tempListItems });
didMountRef.current = true;
}
}, [market]);
return (
<StateContext.Provider value={[state, setState]}>
{props.children}
</StateContext.Provider>
);
};
export { StateContext, StateProvider };
Я пытаюсь использовать reducer вместе с useEffect, но чувствую, что неправильно использую один или оба.