motionless570
motionless570

Reputation: 939

How to filter a data array in reactjs from firestore database

I have a data array that holds all my users and shows them in a list. i want to create a search bar and filter the users based on the entered account number.

i tried to accomplish this by using the filter method, but when i do so, i get an error that my data array is no longer able to accept .map() function

here is my code:

const [data, setData] = useState([]);
const list = []
  const filteredList = []
  useEffect(() => {
    firebase.firestore().collection("Users").get().then((userSnapshot) => {

      userSnapshot.forEach((doc) => {
       
        const {powerAccount,first_name,registerDate,email,company,country,phone} = doc.data();
        setID(doc.data().usersID)
        list.push({
          usersID:doc.id,
          powerAccount:powerAccount,
          first_name:first_name,
          registerDate:registerDate,
          email:email,
          company:company,
          country:country,
          phone:phone,
        });
      });
      setData(list);
    });
  },[]);

function i am using in my searchfield input:

onChange={(e) => data.filter(account => e.target.value == account.powerAccount).map(filteredAccount => (
          //  console.log(filteredAccount)
            
            setData(JSON.stringify(filteredAccount))
          ))} 

in my return:

 return (
 {
after filtering the below code stops working. how can i fix this?
                data.map((user,index) => (
                  <TableRow
                  hover
                  key={user.usersID}>
                  <TableCell>
                      <Box
                        sx={{
                          alignItems: 'center',
                          display: 'flex'
                        }}
                      >
                        <Typography
                          color="textPrimary"
                          variant="body1"
                        >
                          {user.powerAccount}
                        </Typography>
                      </Box>
                    </TableCell>
}
)

Upvotes: 0

Views: 732

Answers (1)

Ga&#235;tan Boyals
Ga&#235;tan Boyals

Reputation: 1228

I didn't realized it at first, but I made you do wrong changes in your code, so I'll write a full answer for clarity.

Since I don't have other information on your code (if and where you store the text field input in a state for example), I will propose a code based on what we have in your post.

You'll have to set 2 different arrays: One with the full data coming from your Firebase db that will be set once, and one with the filtered results.

const [data, setData] = useState([]);
// the only addition I made
const [filteredData, setDilteredData] = useState([]);
// You don't need the following, you don't use it anywhere
// const filteredList = []
  
useEffect(() => {
  const list = []
  firebase.firestore().collection("Users").get().then((userSnapshot) => {

    userSnapshot.forEach((doc) => {
       
      const {powerAccount,first_name,registerDate,email,company,country,phone} = doc.data();
      setID(doc.data().usersID);
      list.push({
        usersID:doc.id,
        powerAccount:powerAccount,
        first_name:first_name,
        registerDate:registerDate,
        email:email,
        company:company,
        country:country,
        phone:phone,
      });
    });
    setData(list);
  });
},[]);

Then, use your full dataset to set a filtered array, based on your condition:

onChange={(e) => {
    setFilteredData(data.filter(account => e.target.value === account.powerAccount))
  }
}

Finally, in your return, check if the length of dataFiltered is greater than 0. If it is, display the filtered data, otherwise simply display the data.

Unfortunately, in your return code posted above, there are missing tags so I cannot write full code for it, but basically, what you have to do is something like this:

return (
  {
    filteredData.length > 0 ? (
      // do here what you did to render your data, but with filteredData instead
      // filteredData.map((user, index) => .......
    ) : (
      // else, render your data in full exactly like your posted code
      // data.map(user, index) => .......
    )

  }
);

You don't even need to setup a second array if you have access to e.target.value in a useState, as mentioned above. You could directly filter in the return method.

Upvotes: 1

Related Questions