Задать вопрос
@mmorrii

Как убрать мерцание графика при перерисовке компонента?

У меня есть компонент с таблицей TablePanel, данные для которой я перебираю с помощью map. В одной из ячейки таблицы есть компонент с графиком LineChartWithoutLegend. Для графика использую библиотеку nivo.

Данные в wsResponseData обновляются ежесекундно и получается так, что при переборе этих данных, ячейки таблицы перерисовываются и вместе с ними компонент с графиком, из-за чего происходит эффект мерцания.

Пробовала выносить график вне map, такого мерцания нет. Также на странице есть другой линейный график у которого мерцания нет.

Подскажите что можно сделать, чтобы избежать такого поведения.

66732dd0d286a408321710.gif

export const TablePanel = () => {
    const wsResponseData = useContext(WsDataContext)
    const httpResponseData = useContext(HttpDataContext)

    return (
        <Table>
            <thead>
                //...
            </thead>
            <tbody>
                { httpResponseData.map(httpData => (
                    wsResponseData[httpData.Names[0]].slice(-1).map((data) => (
                        <tr key={data.keyId}>
                            //...
                            <td>{data.cpu_stats.online_cpus ?
                                <div style={{height: "46px", width: "140px"}}>
                                    <LineChartWithoutLegend containerName={data.name}/>
                                </div> :
                                "null"}
                            </td>
                        </tr>
                    ))
                ))}
            </tbody>
        </Table>
    )
}


export const LineChartWithoutLegend = ({ containerName }: { containerName: string }) => {
    const wsResponseData = useContext(WsDataContext)

    const chartDataRef = useRef<CoordsType[]>(initialLineChartData)

    useEffect(() => {
        const currentTime = getCurrentTime()
        const lastElemTime = chartDataRef.current[chartDataRef.current.length - 1]?.x

        if (currentTime === lastElemTime) return
        
        wsResponseData[containerName]?.slice(-1).map(wsData => {
            chartDataRef.current.push({x: currentTime, y: cpuUsage(wsData)})
        })

        if (chartDataRef.current.length > 30) {
            chartDataRef.current = chartDataRef.current?.slice(-30);
        }
    }, [containerName, wsResponseData]);

    return (
        <ResponsiveLineCanvas
            data={[
                {
                    id: "CPU usage monitoring",
                    data: chartDataRef.current,
                },
            ]}
            // другие настройки для графика
        />
    )
}
  • Вопрос задан
  • 206 просмотров
Подписаться 2 Средний Комментировать
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    Мидл фронтенд-разработчик
    5 месяцев
    Далее
  • Яндекс Практикум
    React-разработчик
    3 месяца
    Далее
  • Яндекс Практикум
    Фронтенд-разработчик
    10 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
@odissey_nemo
Программист, ГИС-системы, растры, космоснимки
Логично сделать так, чтобы компоненты на экране не перерисовывались отдельно друг от друга на каждый чих , а перерисовывались после обновления всех данных в едином цикле. Со средой разработки и библиотеками графики указанного проекта не знаком, но принципы останутся общими, полагаю.
Следует либо останавливать вывод на время обновления, либо вывод организовать в какой то дополнительный буфер (в памяти?), с которого уже и обновлять на регулярной или событийной основе.
Например, при написании графических программ на Java через Swing, также и на Delphi и C# с их библиотеками, полезным оказалось иметь главный буфер в виде Bitmap размером с окно программы, который и использовался для обновления по произвольным событиям (скажем, периодическое обновление всего окна).
Вызвал все процедуры обновления и только тогда сказал repaint. Всё обновится с результирущего буфера, без всякого мигания.
Т.е. смысл в том, чтобы repaint вызывался не из каждого компонента отдельно и асинхронно, а один раз в подходящий момент, после гарантированного завершения всех срочных модификаций или даже на регулярной основе. Мерцания быть не должно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
ITK academy Нижний Новгород
от 50 000 до 90 000 ₽
ITK academy Воронеж
от 50 000 до 90 000 ₽
IT ATLAS Москва
от 200 000 до 250 000 ₽