React Redux filtered by array onChange input

Viewed 72

help me please in Redux filter onInput change! I have two state: 1) items - is array (name number and tel number), 2) search (this state get value by input). When i enter name and phone number and click onSubmit in component will sent state "items". The next i see this contacts on the page. I have another input, his task, filter by contacts array. How can i filtered array state no change him and when filter value === '' i can see all items in state "items".

myStore

import { configureStore } from "@reduxjs/toolkit";
import { createSlice } from "@reduxjs/toolkit";

const contactsSlice = createSlice({
  name: "contacts",
  initialState: {
    items: [],
    search: "",
  },
  reducers: {
    add(state, action) {
      state.items.push(action.payload);
    },
    remove(state, action) {
      state.items = state.items.filter((arrow) => arrow.id !== action.payload);
    },
    search(state, action) {
      state.search = action.payload;

      state.items.filter((item) =>
        item.name.toLowerCase().includes(state.search)
      );
    },
  },
});

export const { add, remove, search } = contactsSlice.actions;

export const store = configureStore({
  reducer: {
    contacts: contactsSlice.reducer,
  },
});

My Component Filter

import { useSelector, useDispatch } from "react-redux";
import { ContainerSearch, Title, Input } from "./Filter.styled";
import { search } from "../Redux/store";

const Filter = () => {
  const dispatch = useDispatch();

  const onChange = (e) => {
    dispatch(search(e.currentTarget.value.toLocaleLowerCase()));
  };

  return (
    <ContainerSearch>
      <Title>Find contacts by name</Title>
      <Input type="text" onChange={onChange} placeholder="Search name" />
    </ContainerSearch>
  );
};

export default Filter;

and my List items

import { useSelector, useDispatch } from "react-redux";
import { remove } from "../Redux/store";
import {
  ContainerList,
  Title,
  Wrapper,
  Item,
  ButtonClose,
  TextList,
} from "./ContactList.styled";

export const List = () => {
  const selector = useSelector((state) => state.contacts.items);
  const dispatch = useDispatch();

  const deleteContact = (contactId) => {
    dispatch(remove(contactId));
  };

  return (
    <ContainerList>
      <Title>Contacts</Title>
      {selector.length > 0 ? (
        <Wrapper>
          {selector.map(({ id, name, number }, index) => (
            <Item key={id} index={index}>
              {name} : {number}
              <ButtonClose onClick={() => deleteContact(id)}>
                &#10007;
              </ButtonClose>
            </Item>
          ))}
        </Wrapper>
      ) : (
        <TextList>No Contacts</TextList>
      )}
    </ContainerList>
  );
};
1 Answers

Do you mean it is working fine, but only wants to show everything in case no searchTerm is provided?

if so, then you can just change the filter logic to:

state.items.filter((item) => {
  const searchTerm = (state.search || "").toLowerCase().trim();
  return searchTerm
    ? (item.name || "").toLowerCase().includes(state.search)
    : true;
});

Related