Home > Enterprise >  How can I get an Array of Objects after iterating array of strings?
How can I get an Array of Objects after iterating array of strings?

Time:08-31

My simple app has:

  • data: array of objects
  • users, setUsers: useState hooks
  • filters: array of strings
  • filteredUsers: it should be an array of objects;

In my app, a user can click and add a string to an array of filters (filters changing), then I'd like to create a new arr of objs filteredUsers, send it to users (by setUsers(filteredUsers)) and render a new list, based on filters.

When I'm using a single string, e.g. getFilteredUsers('string') it works, but I can't make it with an array.


const users = [
    {
  id: 849,
  name: 'John',
  city: 'London',
  languages: ['English']
  },
  
  {
  id: 294,
  name: 'Ola',
  city: 'Stockholm',
  languages: ['Swedish', 'English']
  },
  
  {
  id: 585,
  name: 'Stefano',
  city: 'Naples',
  languages: ['Italian', 'French']
  },
  
  {
  id: 946,
  name: 'Anna',
  city: 'Paris',
  languages: ['French']
  }
]

const four = document.querySelector('.four');
const arrayFilter = arr => {
        const newUsers = filters.map(filter => getUsers(filter));
    four.textContent = JSON.stringify(newUsers);
    return newUsers
}
const test = ['French'];
console.log(arrayFilter(test))

I've also tried to use useEffect, but with no results.

jsfiddle: https://jsfiddle.net/gmp5doqv/165/
GitHub: https://github.com/lukaasz555/job-list/blob/main/components/Main/Main.tsx

CodePudding user response:

This is a function to check a user passes a filter :

const checkUser = (user, filter) =>
  user.name === filter || user.city === filter || user.languages.includes(filter);

This is a function that check a user passes all filters :

let filters = null;
const userFilter = user => {
  for(let i = 0, l = filters.length ; i < l ; i  ) {
    if(!checkUser(user, filters[i])) {
        return false;
    }
  }
  return true;
}

And this is how you can use it :

filters = ['French', 'Naples'];
filteredUsers = users.filter(userFilter);
// gives Stefano, the only one with French and Naples

filters = ['English'];
filteredUsers = users.filter(userFilter);
// gives John and Ola, the only ones with English

filters = [];
filteredUsers = users.filter(userFilter);
// gives everyone !

filters = ['Portuguese'];
filteredUsers = users.filter(userFilter);
// gives no one

CodePudding user response:

Here is an example of preforming this filter using React and the array methods .some and .includes

// Get a hook function
const { useState } = React;

function App() {
    const users = [
      {
        id: 849,
        name: 'John',
        city: 'London',
        languages: ['English']
      },
      {
        id: 294,
        name: 'Ola',
        city: 'Stockholm',
        languages: ['Swedish', 'English']
      },
      {
        id: 585,
        name: 'Stefano',
        city: 'Naples',
        languages: ['Italian', 'French']
      },
      {
        id: 946,
        name: 'Anna',
        city: 'Paris',
        languages: ['French']
      }
    ];
    const languages = [
      'English',
      'Swedish',
      'Italian',
      'French'
    ];
    const [selectedLangs, setSelectedLangs] = useState(
      Object.fromEntries(languages.map(s => [s, false]))
    );
    
    function handleCheckboxClick({target}) {
      const { value, checked } = target;
      const selectedClone = structuredClone(selectedLangs);
      const state = selectedClone[value];
      selectedClone[value] = !state;
      setSelectedLangs(selectedClone);
    }
    
    const selectedLangsThatAreTrue = Object.entries(selectedLangs)
      .filter(([lang, val]) => val)
      .map(([lang]) => lang);
    const targetData = users.filter(
      ({languages}) => 
      languages.some(lan => selectedLangsThatAreTrue.includes(lan))
    );
    
    return (
        <div className="App">
          Select Languages: 
          {
            languages.map(s => (
              <label key={s}> {s} 
                <input value={s} 
                  onClick={handleCheckboxClick}
                  type="checkbox" />
              </label>
            ))
          }
          <br />
          {
            targetData.map(({name}) => <span key={name}> {name} </span>)
          }
          
        </div>
    );
};

// Render it
ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <App />
);
.App label {
  user-select: none;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

  • Related