0

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>
}
)
7
  • From what I see (I could be wrong though, I'm not a JS god), it could come from comparing e.target.value and account.powerAccount via "==" and not "===" (the former does an implicit type coercion), or from the fact that you stringify your data, meaning you have a string now instead of an array. Most likely the second is why your code doesn't work anymore. Commented Nov 8, 2021 at 14:50
  • even without stringify it does not work, because apparently it stops being an array and becomes an object. @GaëtanBoyals Commented Nov 8, 2021 at 14:52
  • Ah, I didn't read correctly. You don't have to map anything, Array.prototype.filter returns a newly created array with only the values passing the condition. Your code can be simplified to setData(data.filter(account => e.target.value === account.powerAccount)). Commented Nov 8, 2021 at 14:58
  • @GaëtanBoyals that worked! thank you so much Commented Nov 8, 2021 at 15:06
  • @GaëtanBoyals one small problem now, is that once i type anything the data gets cleared because it is being called with the onChange method. how do i let it such that it sets the data once the two values are equal? Commented Nov 8, 2021 at 15:16

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.