React Native: не удается использовать функцию в качестве перехвата состояния по умолчанию? проблема с вычислением массива и медленным пользовательским интерфейсом

#javascript #reactjs #react-native

#javascript #reactjs #react-native

Вопрос:

У меня есть функция, которая принимает несколько скидок и группирует их по дням, поэтому конечным результатом является массив из 7, представляющий каждый день с несколькими скидками или без них в каждом индексе, по какой-то причине это вычисление делает пользовательский интерфейс не очень быстрым, только полностью завершается, когда я нажимаю на пользовательский интерфейс и нажимаюперед этим отображается незавершенный пользовательский интерфейс…

Я попытался поместить функцию, которая возвращает мне результирующий массив в состояние по умолчанию моего перехвата состояния, но я получил следующую ошибку:

 getVenueDiscounts is not a function
 

До этого я использовал useEffect с пустым массивом, чтобы получить свой массив, но, как я уже сказал, это было не очень быстро…

Вот мой метод, возможно, проблема в том, что я не оптимизировал свою бизнес-логику, можно ли сделать эти вычисления лучше, возможно, с помощью метода Lodash?

Мой метод группировки скидок по дням недели:

 const [ weekDiscounts, setWeekDiscounts ] = useState(getVenueDiscounts());

const getVenueDiscounts = () =>
    {
        if(discounts.length == 0)
        {
        var weekDiscountsCopy = [ [], [], [], [], [], [], [] ];
        
        //let weekDiscountsCopy = [...weekDiscounts];
        //let response = await venueStore.getVenueDiscounts({ id:1 });
        console.log(response.data);
        let allDiscounts = _.cloneDeep(venueStore.myDiscounts);
        //let allDiscounts = response.data.discounts;
        //Alert.alert(response.data.discounts.length ' discounts');
        //setDiscounts(discounts);
        console.log(response.data.discounts[0].days);
        for(var i=0; i<response.data.discounts.length;i  )
        {
            let discountDays = allDiscounts[i].days;
            for(var x=0; x<discountDays.length;x  )
            {
                if(discountDays[x].id == 1) 
                {
                    weekDiscountsCopy[0].push(allDiscounts[i]);
                }
                else if(discountDays[x].id == 2) 
                {
                    weekDiscountsCopy[1].push(allDiscounts[i]);
                }
                else if(discountDays[x].id == 3) 
                {
                    weekDiscountsCopy[2].push(allDiscounts[i]);
                }
                else if(discountDays[x].id == 4) 
                {
                    weekDiscountsCopy[3].push(allDiscounts[i]);
                }
                else if(discountDays[x].id == 5) 
                {
                    weekDiscountsCopy[4].push(allDiscounts[i]);
                }
                else if(discountDays[x].id == 6) 
                {
                    weekDiscountsCopy[5].push(allDiscounts[i]);
                }
                else if(discountDays[x].id == 7)
                {
                    weekDiscountsCopy[6].push(allDiscounts[i]);
                }
            }
            //setWeekDiscounts(weekDiscountsCopy);
            setDiscounts(allDiscounts);
            return weekDiscountsCopy;
        }
    }
    };
 

Заранее спасибо!

Ответ №1:

Это проблема того, как и когда интерпретируется ваш код.

Поскольку getVenueDiscounts лямбда-выражение присваивается константе, оно поднимается на вершину области видимости, но остается неопределенным до тех пор, пока этот код фактически не будет выполнен на втором проходе — и перехват состояния инициализируется этим вызовом до того, как функция была определена. Одним из решений было бы просто переместиться getVenueDiscounts выше перехвата.

Более подробное описание можно найти здесь:

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

Ответ №2:

Причина ошибки

Ну, вы пропустили фундаментальную концепцию программирования, что нельзя обращаться к переменной, функции и т. Д. Перед инициализацией.

MCVE

Минимальным, воспроизводимым примером вашей ошибки может быть попытка доступа bar до ее инициализации.

 
const foo = () => {
  bar();
  ^^^^^ // Uncaught ReferenceError: Cannot access 'bar' before initialization
  const bar = () => console.log('I worked!');
};

foo();
 

Решение

Для вашей проблемы может быть два решения:

  1. Объявляйте getVenueDiscounts() функцию перед useState() перехватом.
 
const getVenueDiscounts = () => {
  // logic goes here
}

const [ weekDiscounts, setWeekDiscounts ] = useState(getVenueDiscounts());

 
  1. Лучшим подходом было бы использовать useMemo() перехват, который возвращал бы кэшированное значение, если зависимости в массиве не изменяются.
 
const weekDiscounts = useMemo(() => {
  // getVenueDiscounts() logic goes here
},[]); // list of dependencies on which weekDiscounts depends on