Фильтрация на стороне клиента с помощью useReducer

#reactjs #filter #react-hooks

#reactjs #Фильтр #реагирующие хуки

Вопрос:

У меня есть таблица транзакций, которая содержит некоторые данные. Я пытаюсь создать фильтр на стороне клиента при замене ввода поиска.

Сначала это работает, при следующем событии onChange фильтруются ранее отфильтрованные данные, а не исходные данные.

Как я могу сделать так, чтобы он всегда фильтровал начальное состояние при каждом событии onChange?

Если есть лучший подход для этого, пожалуйста, скажите мне

 //Table
const [transactions, setTransactions] = useReducer(
    transactionsReducer,
    fetchTransactions()
  )
  
 //Reducer
const transactionsReducer = (state, action) => {
  switch (action.type) {
    case 'filter':
      return action.transactions.filter(item =>
        item.description.includes(action.searchTerm)
      )

    default:
      return state
  }
}
  
 //Search component (it receives setTransactions function as a prop)
const Search = ({ setTransactions }) => {
  const handleChange = event => {
    setTransactions({
      type: 'filter',
      searchTerm: event.target.value
    })
  }

  return (
    <form>
      <Input
        type="text"
        name="search"
        placeholder="search"
        onChange={handleChange}
      />
    </form>
  )
}
  

Комментарии:

1. Ваш редуктор должен возвращать как исходные данные, так и отфильтрованные данные. В настоящее время редуктор возвращает только отфильтрованные данные, поэтому при следующем onChange вызове so filter будет работать с ранее отфильтрованными данными. Или вы можете использовать другой подход, выполнив фильтрацию внутри onChange и установив отфильтрованное значение в другом локальном состоянии.

2. Я пытаюсь не использовать для этого другое состояние. «Ваш редуктор должен возвращать как исходные, так и отфильтрованные данные», как именно я могу это сделать?

3. В принципе, ваше начальное состояние для useReducer будет иметь форму, подобную {transaction: fetchTransactions(), filtered: []} . Когда вы отправляете filter тип, ваш редуктор должен фильтровать filtered = yourFilterFunction(state.transactions) и возвращать его как {...state, filter: filtered} . И вы можете получить доступ к отфильтрованным транзакциям как transactions.filtered внутри вашего компонента

Ответ №1:

Я передал транзакции в компонент поиска из fetchTransactions() следующим образом

 <Search
  setTransactions={setTransactions}
  transactions={fetchTransactions()}
/>
  

а затем передайте эти транзакции моему редуктору в качестве действия:

 const handleChange = event => {
   setTransactions({
     type: 'filter',
     transactions, //like this
     searchTerm: event.target.value
   })
}
  

и отфильтруйте эти транзакции в моем редукторе:

 const transactionsReducer = (state, action) => {
  switch (action.type) {
    case 'filter':
      return action.transactions.filter(item =>
        item.description.includes(action.searchTerm)
      )

    default:
      return state
  }
}
  

и это работает нормально. Если есть лучшие подходы к этому, пожалуйста, дайте мне знать