N
N
Nikita Kit2019-09-11 19:54:07
React
Nikita Kit, 2019-09-11 19:54:07

Why do svg icons from a sprite flicker when state is updated?

This is my first react project, to be honest, it is full of mystical surprises, I have been struggling with this for a long time and just don’t know where to dig.
Generally there is a component - temporary. A stateful wrapper for UI components. I wrote a button, a checkbox, threw a callback from the wrapper at onChange of the checkbox, in which I described setState, and as a result, all my svg icons (everything, even those outside the checkbox) blink when re-rendering.
That is, it turns out that I return the state to the react and it stupidly re-renders the entire tree that depends on the state, as if not even trying to understand what has changed. I wrote in vue before react and have never come across anything like this. Unless if I intentionally changed some specific icon, but then I just changed a piece of the state, and React just brazenly re-renders everything.
I tried to return the whole state instead . Hoping that the react is smart, it will merge the changes and re-render exactly what was poured into setState. I have never been so wrong. In general, everything looks like this.
this.setState({checkboxes: {[argKey]: {value}]}})

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;

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
Nikita Kit, 2019-09-12
@ShadowOfCasper

I know it's crazy to highlight my answer as a solution, but in general I decided to find help in the react rep and I was pushed to the solution . I deployed a clean project and tried to recreate the problem step by step.
In general, the decision is strange. According to the react docks - if you create a PureComponent, then down the tree below all the children should be PureComponent. So I hesitated to try and make UiWrapper clean. I have checkboxes, buttons and radio buttons all wrapped in UiWrapper. At the same time, they are inherited from Component and I did not have to update them through shouldUpdate.
Nevertheless, for the future, if someone encounters blinking pictures or icons, mb this will help him. On the open spaces of Google, I found similar problems, but related to React Native, not DOM

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question