Answer the question
In order to leave comments, you need to log in
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
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 questionAsk a Question
731 491 924 answers to any question