ShadowOfCasper
@ShadowOfCasper
Middle User Interface Web Developer

Почему svg иконки из спрайта мигают при обновлении state?

Это мой первый проект на реакте, честно говоря он полон мистических сюрпризов, с этим я уже долго борюсь и уже просто не знаю куда копать.
Вообщем есть компонент - временный. Обёртка с состоянием для UI компонентов. Написал кнопку, чекбокс, прокинул колбэк с обёртки при onChange чекбокса, в котором описал setState, и по итогу у меня все svg иконки (прямо вообще все, даже те что вне чекбокса) мигают при ре-рендере.
То есть, получается, я реакту возвращаю стейт и он ре-рендерит тупо всё дерево, зависящее от стейта, как будто даже не пытаясь понять что конеретно поменялось. Я писал на vue до реакта и никогда ни с чем подобным не сталкивался. Разве что если я преднамеренно изменял какую-то конкретную иконку, но тут я просто поменял кусочек стейта, а реакт просто внаглую ререндерит всё.
Я пытался вместо целого стейта вернуть
this.setState({checkboxes: {[argKey]: {value}]}})
Надеясь что реакт умный, смержит изменения и ререндерит конкретно то, что было влито в setState. Я ещё никогда так не ошибался.
Вообщем выглядит всё так.
import React from 'react';
import './App.css';
import Icon from './components/common/Icon';
import Button from './components/common/Button';
import Checkbox from './components/common/Checkbox';



class Uikit extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      checkboxes: {
        first: {
          value: true
        },
        second: {
          value: false
        },
        third: {
          value: false
        }
      },
      radio: {
        first: {
          value: true
        },
        second: {
          value: false
        },
        third: {
          value: false
        }
      }
    }
    this.updateCheckboxState = this.updateCheckboxState.bind(this);
  }

  updateCheckboxState(argKey, value) {
    this.setState((state) => {
        state.checkboxes[argKey].value = value;
        return Object.assign({}, state);
    })
  }

  render() {
    function UiWrapper (props) {
      return <div className='p-5 border border-dashed border-ui-blue'>{props.children}</div>
    }
    return <div className='kit-grid'>
      <UiWrapper>
        <Button /*narrow*/ /*thin*/ /*secondary*/ /*disabled*/ /*iconed - only for single icon*/>
          <Icon name='plus' className='mr-2 icon--sm stroke-dark'/>
          Плюс
        </Button>
      </UiWrapper>
      <UiWrapper>
        {Object.keys(this.state.checkboxes).map((key) => {
          return <Checkbox checked={this.state.checkboxes[key].value}
                  key={key} 
                  onChange={this.updateCheckboxState}
                  id={key} label={key}/>
        })}
      </UiWrapper>
    </div>
  }
}

export default Uikit;
  • Вопрос задан
  • 303 просмотра
Решения вопроса 1
ShadowOfCasper
@ShadowOfCasper Автор вопроса
Middle User Interface Web Developer
Я знаю - это дичь, выделять свой ответ как решение, но вообщем-то я решил найти помощи в репе реакта и меня натолкнули на решение. Я развернул чистый проект и пробовал воссоздать проблему шаг за шагом.
Вообще решение странное. По докам реакта - если ты создаёшь PureComponent, то и по дереву ниже все дочки должны быть PureComponent. Поэтому я не решался пробовать сделать UiWrapper чистым. У меня чекбоксы, кнопки и радиокнопки все обёрнуты в UiWrapper. При этом они наследуются от Component и через shouldUpdate мне их обновлять не пришлось.
Тем не менее на будущее, если кто-то столкнётся с морганием картинок или иконок, мб ему это поможет. На просторах гугла я находил подобные проблемы, но связанные с React Native, а не DOM
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы