Reputation: 177
I am trying to imitate the behaviour of a checkbox by switching custom checkbox images depending on the condition (true or false). I get a very annoying visual bug where as I set state to the truthy or falsy condition the images depending on it and the box does a little flickr before switching, here's my code:
import React from 'react';
import boxCheckedIcon from '../../../../assets/SmallBoxChecked.svg';
import boxUncheckedIcon from '../../../../assets/SmallBoxUnchecked.svg';
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
condition: false,
}
}
handleSelect = () => {
this.setState(prevState => ({
condition: !prevState.condition
}));
}
renderCheckbox = condition => {
return condition ? <img
id="checkedCheck"
src={boxCheckedIcon}
alt="checked check box"
/> : <img
id="uncheckedCheck"
src={boxUncheckedIcon}
alt="unchecked check box"
/>
};
render() {
const { condition } = this.state;
return (
<div onClick={() => handleSelect()}>
{renderCheckbox(condition)}
</div>
);
}
}
any idea how to make the transition between the two images smoother? CSS, React or otherwise..
Upvotes: 4
Views: 372
Reputation: 272146
Try specifying the dimensions on the image. Missing image dimensions could cause reflows because the browser has to load the image to see its dimensions and it will temporarily collapse the area used by the image causing everything below the image to jump around.
Upvotes: 1
Reputation: 16264
If you're using Create React App, you can use svg components instead of img
tag.
import { ReactComponent as Checked } from '../assets/checked.svg'
import { ReactComponent as Unchecked } from '../assets/unchecked.svg'
// Use it like this
return condition ? <Checked/> : <Unchecked/>
Upvotes: 1
Reputation: 26075
Problem is that every time you render different img
tag, browser will fetch/download images again. Without using any font libraries, you can avoid this situation by rendering both images on the DOM and hiding/showing them based on condition:
renderCheckbox = (condition) => {
return (
<>
<img
heigth="40"
width="40"
id="checkedCheck"
src={boxCheckedIcon}
alt="checked check box"
className={condition ? "" : "hidden"}
/>
<img
heigth="40"
width="40"
id="uncheckedCheck"
src={boxUncheckedIcon}
alt="unchecked check box"
className={condition ? "hidden" : ""}
/>
</>
);
};
and in your style.css file you can add hidden class:
.hidden {
display: none;
}
take a look at this codesandbox.
Upvotes: 3
Reputation: 522
The most correct would be to move your images to a CSS-sprite and switch it background-position by an additional class
render() {
const { condition } = this.state;
return (
<div
className={classNames(
'checkbox__icon',
condition && 'is-checked',
)}
onClick={this.handleSelect}
/>
);
}
In the example, I use the lib https://www.npmjs.com/package/classnames
Upvotes: 3