Эффект использования, перезаписывает оператор if

#javascript #reactjs #react-hooks

Вопрос:

Я пытаюсь отсортировать список, упорядочив его по значению объекта , но с useState помощью операторов if, которые запускаются только в операторе if, но не в обоих if и else :

 const { countryList } = useCustomerData();
useEffect(()=>{
    if(type === 'nationality'){
      countryList.sort((a: CountryObject, b: CountryObject) =>
        a.nationality.localeCompare(b.nationality))
    }else {
      countryList.sort((a: CountryObject, b: CountryObject) =>
        a.country.localeCompare(b.country))
    }
  }, [countryList, type])
 

Это кантрилист :

 [{country: 'Afghanistan', code: 'AF', prefix: '93', nationality: 'Afghan'}
1: {country: 'Ägypten', code: 'EG', prefix: '20', nationality: 'Egyptian'}
2: {country: 'Åland-Inseln', code: 'AX', prefix: ' 358-18', nationality: 'Åland-Inseln'}
3: {country: 'Albanien', code: 'AL', prefix: '355', nationality: 'Albanisch'}
4: {country: 'Algerien', code: 'DZ', prefix: '213', nationality: 'Algerian'}]
 

Список очень длинный, но это примерный список.

МОЯ ВТОРАЯ ПОПЫТКА :

 const [countryFinal, setCountryFinal] = useState<CountryType[]>([])


  const value = useMemo(() => _get(values, name), [values, name]);

  useEffect(()=>{
    if(type === 'nationality'){
      setCountryFinal(countryList.sort((a: CountryObject, b: CountryObject) =>
        a.nationality.localeCompare(b.nationality)))
    }else {
      setCountryFinal(countryList.sort((a: CountryObject, b: CountryObject) =>
        a.country.localeCompare(b.country)))
    }
  }, [countryList, type, setCountryFinal])
 

Это тоже не удалось.

для получения дополнительной информации ознакомьтесь с этим кодом

Комментарии:

1. Является countryList частью вашего состояния компонента? Потому что, если это так, вы нарушаете фундаментальное правило состояния реакции: вы не можете напрямую изменять значения состояния, вместо этого вам нужно создать новое значение. Итак: setCountryList(countryList.slice().sort(/*...*/)); .

2. @Ти Джей Краудер, я пробовал что-то подобное , но была та же проблема, кстати, список стран взят из контекста : const { countryList } = useCustomerData();

3. Вы также не можете напрямую изменять элементы контекста. Если вам нужна отсортированная версия, вам придется скопировать ее в состояние, а затем отсортировать.

4. Как вы определяете else , что ветвь не активирована? Я не вижу pb в этом фрагменте кода.

5. @T. J. Краудер и , я изменил свой код со второй попытки, но все равно не сработало. Простите меня за утверждение, что вы не можете изменять прямые элементы ? Я думаю, что я сделал это

Ответ №1:

Вы сказали, что список стран (косвенно) взят из контекста. Вы не можете напрямую изменять элементы контекста подобным образом. Если вы хотите, чтобы компонент имел свой собственный порядок сортировки для этого списка, вам придется сортировать его при каждом рендеринге (возможно, не идеально) или сохранять отсортированную версию в состоянии, обновляя ее по мере необходимости.

Что-то в этом роде:

 const { countryList } = useCustomerData();
const [ sortedCountryList, setSortedCountryList ] = useState<CountryObject[]>([]); // (Or you could init it with `countryList`)

useEffect(()=>{
    if (type === "nationality"){
        setSortedCountryList(countryList.slice().sort((a: CountryObject, b: CountryObject) =>
            a.nationality.localeCompare(b.nationality)
        ));
    } else {
        setSortedCountryList(countryList.slice().sort((a: CountryObject, b: CountryObject) =>
            a.country.localeCompare(b.country)
        ));
    }
}, [countryList, type]); // <=== Update the sorted list when either the context
                         // value or the sort type changes

// ...use `sortedCountryList` for rendering