График обновляется дважды

#reactjs #charts

Вопрос:

Диаграмма, созданная с использованием react-chartjs-2 и chartjs, обновляется 2 раза при изменении значений. В первый раз меняется только форма графика, а во второй раз меняются значения по осям y и x.

 const Chart = ({country}) => {
    const [dailyData,setDailyData] = useState([]);
    useEffect(() => {
        const fetchAPI = async () => {
            setDailyData(await fetchDailyData(country))
        }
        fetchAPI();
    },[country]);
   const {day,infected,recoveries,deaths} = dailyData;
    const lineChart = (
        infected? (<Line
        data={{
            labels: day.map((data ) => (data)),
            datasets:[
                {
                    data:  infected.map((data) => (data)),
                    label: 'Infected',
                    borderColor: '#3333ff',
                    fill: true,
                }],
        }}
        /> ) : null

      
    )
 

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

1. почему вы помещаете определение fetchAPI в useEffect?

2. Возможно, вы захотите попробовать изменить useEffect для useLayoutEffect, чтобы предотвратить асинхронное рисование React.

3. @AnoopJoshi, помещающий fetchAPI в useEffect, — это способ предотвратить реакцию на то, чтобы кричать на вас за то, что вы не помещаете «fetchAPI» в зависимости от эффекта использования. Что, если вы действительно выведете fetchAPI наружу и добавите его в качестве зависимости от эффекта использования, вы получите бесконечный цикл. Что вам придется исправить, обернув fetchAPI крючком useCallback и т. Д., В любом случае, это не так уж плохо.

4. @BaltasarSolanilla Я попытался использовать useLayoutEffect, но все равно столкнулся с той же проблемой.

5. Извините, я мало что могу с этим поделать. Я бы рекомендовал вам создать песочницу с минимальным воспроизводимым примером, это не слишком много кода, должно быть легко. Может быть, кто-то еще заметит эту проблему.

Ответ №1:

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

 const asd=[1,2,4,5];

const {a,b,c}=asd;

console.log (a,b,c); // undefined, undefined, undefined

const [e,f,g]=asd; 

console.log (e,f,g); // 1,2,4 

Однако вы сказали, что ваша диаграмма работает после второй вспышки. Это означает, что ваш исходный пустой массив не является правильным значением по умолчанию для useState крючка. Следует использовать null и проверить это, прежде чем разрушать его.

ОБНОВЛЕНИЕ: Диаграмма может мигать дважды, если данные также загружаются дважды. useEffect должен быть оператор if, проверяющий, были ли данные уже загружены, и загружайте только в том случае, если это не так. Возможно, вы могли бы добавить другое состояние для загрузки. таким образом, у вас не будет двух одновременных вызовов API.

Ваш код будет выглядеть следующим образом:

 const Chart = ({country}) => {
    const [dailyData,setDailyData] = useState(null);
    useEffect(() => {
        if(country amp;amp; !dailyData){
          const fetchAPI = async () => {
            
            setDailyData(await fetchDailyData(country))
          }
          fetchAPI();
        }
    },[country]);
    let lineChart=null
    if (dailyData){
        const {day,infected,recoveries,deaths} = dailyData;
        lineChart = (<Line
            data={{
                labels: day.map((data ) => (data)),
                datasets:[
                    {
                        data:  infected.map((data) => (data)),
                        label: 'Infected',
                        borderColor: '#3333ff',
                        fill: true,
                    }],
            }}
        /> )
    }
}
 

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

1. Спасибо за ответ, но он все равно освежает дважды.

2. Но теперь он показывает данные первой выбранной страны. Может быть, это не подходит для других из-за ! Состояние ежедневных данных.

3. Вы можете проверить, относятся ли текущие загруженные данные к текущей стране. Если это не так, то загрузите его для текущей страны. Это должно быть в том же состоянии, где ! Ежедневные данные есть.