R
R
rgdzv2021-01-28 12:18:31
JavaScript
rgdzv, 2021-01-28 12:18:31

What is the correct way to use the createSelector function (reselect library) with the useSelector hook in a React app?

I'm making a React project. App component code:

const App = () => {

  //const { tickets, isFetching, error } = useSelector(({ tickets }) => tickets)  // <- эта строка хорошо отрабатывает

  const { isFetching } = useSelector(({ tickets }) => tickets)
  const tickets = useSelector(sorterSelector)                         //  <- возвращает undefined

  const dispatch = useDispatch()

  const renderedTickets = tickets.map((ticket) => {            //  <- проблема - TypeError: Cannot read property 'map' of 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/>
          </div>
          {isFetching 
            ? 
              <img src={preloader} alt="preloader"/>
            : 
              <div className="content__item__tickets">
                {renderedTickets}
              </div>
          }
        </div>
      </div>
    </div>
  )
}


Selector code:

const allTickets = state => state.tickets
const selected = state => state.sorter.selected

export const sorterSelector = createSelector(
  [allTickets, selected],
  (tickets, selec) => {                                         // <- tickets - пустой массив
    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)
      })
    }
  }
)


The first commented line in the App component (where I destructure the object) works well: I get tickets from the server and display them in the component. But I need to add side effects to the array of tickets (sorting, filtering), so I decided to use a selector.

However, when using such a notation const tickets = useSelector(sorterSelector), the selector returns undefined (error ). With this notation and the logic I described in the sorterSelector, I don't even see the fetchData function in the useEffect of the App component run. How to solve this problem? Recording useTypeError: Cannot read property 'map' of undefined

const tickets = useSelector(state => sorterSelector(state))
also doesn't help. The fetchData function doesn't run, the selector remains undefined.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question