OyeeRatio
OyeeRatio

Reputation: 225

How to filter an array without losing data?

I have a function to filter an array of todos. The array is filtered correctly but when I type some thing else it removes other array elements and doesn't go back.

I've seen a few solutions, but they say "you have to write code in the render function" and I don't use this method because I render the array elsewhere with the help of props. filteredTodos has all local storage data.

How can I filter this data without losing data?

// *** Form.js ***
  const filterTodos = (e) => {
    const filtTod = filteredTodos.filter((todo) => {
      return todo.text.toLowerCase().indexOf(e.target.value.toLowerCase()) !== -1
    });
    setFilteredTodos([...filtTod]);
  };
// it's my render place *** TodoList.js ***
return (
    <div className="todo-container">
      <ul className="todo-list">
        {filteredTodos.map((todo) => {
          return (
            <Todo
            id={todo.id}
            key={todo.id}
            text={todo.text}
            completed={todo.completed}
            setTodos={setTodos}
            todos={todos}
          />
          )
        })}
      </ul>
    </div>
  );
const [inputText, setInputText] = useState("");
  const [todos, setTodos] = useState([]); // Todos is all array items.
  const [status, setStatus] = useState("all");
  const [filteredTodos, setFilteredTodos] = useState([]); // the state is for my filter list

Upvotes: 1

Views: 2096

Answers (1)

ggorlen
ggorlen

Reputation: 57394

The idea with filtering data like an array of todos is to maintain a consistent "reference" or "source" array that represents all of the todos that exist in your app. This reference array may change when the user adds or removes a todo item, and may be persisted to the backend (or local storage, in your case) in some capacity or other. This array is the source of truth.

When a user enters a search/filtering term, filter on the reference/source array of all todos every time rather than the already-filtered result set.

In your code, todos represents the source array and filteredTodos represents the results of a single search. By using filteredTodos.filter, the results either keep diminishing after each filtering query, or there never were any results to work with to begin with -- either way, it's incorrect.

Think of filteredTodos as a temporary snapshot of todos used to show a subset view of todos to match the user's search term.

The fix is to use todos.filter rather than filteredTodos.filter so that you're always searching on the full data set.

Upvotes: 1

Related Questions