Do you want to request a feature or report a bug?
Bug.
What is the current behavior?
I update state of chechbox from parent and after setState executed on parent all tree starts to re-render and icons blink.
What is the expected behavior?
I update state of chechbox from parent and expect re-render only for checked checkbox.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
I use latest version of create-react app.
So, this is my first react app and I dont like how webpack and react works with SVG. I want to create one static svg symbol sprite and render all icons by their name, which I pass from props.
import React from 'react';
import PropTypes from 'prop-types';
class Icon extends React.Component {
getSprite() {
let icon = require(`../../assets/icons/sprite.svg`);
return icon;
}
render() {
return <svg className={`icon ${this.props.className ? this.props.className : ''}`} viewBox="0 0 18 18" width="24">
<use xlinkHref={`${this.getSprite()}#${this.props.name}`} />
</svg>
}
}
Icon.propTypes = {
name: PropTypes.string.isRequired,
};
export default Icon
Sprite has rendered by gulp task cause with webpack its too difficult and webpack cant modify svg like I need. So, I start to write Ui kit for project - create UiKit component and add some states for children.
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>
}
}
When updateCheckboxState executed all UiKit re-rendered, icons blink and i'm gets angry. Why?
I tried to updaate setState inners and return only checkboxes. No changes....
updateCheckboxState(argKey, value) {
this.setState((state) => {
let old = {}
Object.keys(state.checkboxes).forEach(key => {
if (key !== argKey) old[key] = state.checkboxes[key]
});
state.checkboxes[argKey].value = value;
return Object.assign({}, {checkboxes: {[argKey]: {value}, ...old }});
})
}
All component tree re-render, all icons blink
Hi @WebKieth , could you kindly reproduce the issue on codesandbox that way it may be easier to debug the problem you're facing
Try to use PureComponent for Icon class component or turn it to functional component and use memo
https://reactjs.org/docs/react-api.html#reactpurecomponent
https://reactjs.org/docs/react-api.html#reactmemo
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import icon from '../../assets/icons/sprite.svg';
const Icon = () => (
<svg className={`icon ${props.className ?props.className : ''}`} viewBox="0 0 18 18" width="24">
<use xlinkHref={`${icon}#${props.name}`} />
</svg>
);
Icon.propTypes = {
name: PropTypes.string.isRequired,
};
export default memo(Icon);
@esulimenko I did it and blinks view longer
@Tevinthuku I sets new repo about this problem in the evening, today.
And thanks for helping, I appreciate it.
@Tevinthuku @esulimenko I tried to repoduce it on clean create-react-app and found a reason of this problem.
I wrapped all new components into UiWrapper, to prevent component sticking. On clean repo, when I render icons with checkbox and update App state react updated DOM correctly. When I add UiWrapper - problem appear. So, I just add PureComponent extending on UiWrapper and all works correctly.
Most helpful comment
@Tevinthuku @esulimenko I tried to repoduce it on clean create-react-app and found a reason of this problem.
I wrapped all new components into UiWrapper, to prevent component sticking. On clean repo, when I render icons with checkbox and update App state react updated DOM correctly. When I add UiWrapper - problem appear. So, I just add PureComponent extending on UiWrapper and all works correctly.