Как правильно использовать функцию createSelector (библиотека reselect) с хуком useSelector в приложении React?
Делаю проект на React. Код компонента App:
const App = () => {
//const { tickets, isFetching, error } = useSelector(({ tickets }) => tickets) // <- эта строка работает хорошо
const { sorterTabs, selected } = useSelector(({ sorter }) => sorter)
const { isFetching } = useSelector(({ tickets }) => tickets)
const dispatch = useDispatch()
const tickets = useSelector(sorterSelector) // <- эта строка не работает, селектор возвращает undefined!
const handleSorterClick = ({ target }) => {
dispatch(getSelectedSorter(target.getAttribute('name')))
}
const renderedTickets = tickets.map((ticket) => { // <- проблема, tickets is undefined
const src = `http://pics.avs.io/99/36/${ticket.carrier}.png`
return (
<Ticket
key={ticket.price + ticket.segments[0].duration}
ticket={ticket}
price={ticket.price}
src={src}
segment={ticket.segments}
/>
)
}).slice(0,5)
useEffect(() => {
dispatch(fetchData())
}, [])
return (
<div className="container">
<Header />
<div className="content">
<Filter />
<div className="content__item">
<div className="content__item__sorting">
<Sorter
sorterTabs={sorterTabs}
selected={selected}
handleSorterClick={handleSorterClick}
/>
</div>
{isFetching
?
<img src={preloader} alt="preloader"/>
:
<div className="content__item__tickets">
{renderedTickets}
</div>
}
</div>
</div>
</div>
)
}
Код для селектора:
const allTickets = state => state.tickets
const selected = state => state.sorter.selected
export const sorterSelector = createSelector(
[allTickets, selected],
(tickets, selec) => { // <- tickets undefined!
if (tickets.isFetching || tickets.error) {
return []
}
if (selec === "Самый дешевый") {
[...tickets.tickets].sort((a, b) => {
return a.price - b.price
})
} else {
[...tickets.tickets].sort((a, b) => {
return (a.segments[0].duration + a.segments[1].duration) - (b.segments[0].duration + b.segments[1].duration)
})
}
}
)
Первая закомментированная строка в компоненте App (где я деструктурирую объект) работает хорошо: я получаю билеты с сервера и отображаю их в компоненте. Но мне необходимо добавить сайд-эффекты в массив билетов (сортировка, фильтрация), поэтому я решил использовать селектор.
Однако, при использовании такой записи const tickets = useSelector(sorterSelector), селектор возвращает undefined (ошибка TypeError: Cannot read property 'map' of undefined). При данной записи и логике, которую я описал в sorterSelector, я даже не вижу, что функция fetchData в useEffect запускается.
Как решить эту проблему?
Ответы (1 шт):
Ошибка крылась в правильном возврате отсортированного массива в селекторе:
const allTickets = state => state.tickets
const selected = state => state.sorter.selected
export const sorterSelector = createSelector(
[allTickets, selected],
(tickets, selec) => {
if (tickets.isFetching || tickets.error) {
return []
}
if (selec === "Самый дешевый") {
return [...tickets.tickets].sort((a, b) => a.price - b.price)
} else {
return [...tickets.tickets].sort((a, b) => (a.segments[0].duration + a.segments[1].duration) - (b.segments[0].duration + b.segments[1].duration))
})
}
}
)