Home > Enterprise >  React - filter object with useEffect
React - filter object with useEffect

Time:07-27

I have an object about languages.

export const languageOptions = {
  en: {country: 'En', flag: require('../icons/ukflag.png')},
  ru: {country: 'Ru', flag: require('../icons/ruflag.png')},
  de: {country: 'De', flag: require('../icons/deflag.png')},
};

I want to filter when rendering components. I want to show droplist just en and de. I used useEffect, but it seems not working. After first click everything is working. No at the first rendering is not working.

const [selectedOption, setSelectedOption] = useState("Ru");
const [langListFiltered, setLangListFiltered] = useState();

useEffect(() => {
    setLangListFiltered(
      Object.fromEntries(
        Object.entries(languageOptions).filter(
          ([key]) => !key.includes(selectedOption)
        )
      )
    );
  }, [selectedOption]);

at the beginning

after click to change language

CodePudding user response:

Either change your object of language to (here I changed keys of object):

export const languageOptions = {
  En: {country: 'En', flag: require('../icons/ukflag.png')},
  Ru: {country: 'Ru', flag: require('../icons/ruflag.png')},
  De: {country: 'De', flag: require('../icons/deflag.png')},
};

Or Change state initial value:

const [selectedOption, setSelectedOption] = useState("ru");
const [langListFiltered, setLangListFiltered] = useState();

useEffect(() => {
    setLangListFiltered(
      Object.fromEntries(
        Object.entries(languageOptions).filter(
          ([key]) => !key.includes(selectedOption)
        )
      )
    );
  }, [selectedOption]);

You need to go for any of the above solutions in order to solve your problem. I just changed values in the above solutions as they were not the same to do the comparison.

CodePudding user response:

It is better to not store data in state which can be derived from state. Also, you don't need useEffect in this case, just do:

 const langListFiltered = React.useMemo(() => {
    return Object.fromEntries(
      Object.entries(languageOptions).filter(
        ([key]) => !key.includes(selectedOption)
      )
    );
  }, [selectedOption]);

PS. Reason why it didn't work in your case was your initial value of useState was "Ru" instead of "ru".

  • Related