Reputation: 109
I'm trying to put a React-Icons into innerHTML of element whenever I clicked it.
like this: target.innerHTML = '<ImCross/>';
But it always failed to show the icons. BUT It will work perfectly if I'm using another element like <span></span>
and just put some letters in it. So, is there a way to put an Icon into InnerHtml?
This is the example of my code:
import { ImCross } from "https://cdn.skypack.dev/react-icons/im";
const App = () => {
const box = {
backgroundColor: '#000',
width: 150,
height: 140
}
const symbol = {
color: '#fff',
textAlign: 'center',
position: 'relative',
top: 30,
fontSize: 70
}
const handleClickedBox = (e) => {
const target = e.currentTarget.querySelector('.symbol');
// THIS IS FAILED TO SHOW THE ICON
target.innerHTML = '<ImCross/>';
// THIS DOESN'T WORK TOO
target.innerHTML = '<span> <ImCross/> </span>';
// BUT THIS ONE IS WORK
target.innerHTML = '<span>X</span>';
}
return (
<div>
{/* This is the box that will be clicked */}
<div onClick={(e) => handleClickedBox(e)} style={box}>
{/* This is element that it's innerHTML will show the symbol */}
<div className='symbol' style={symbol}></div>
</div>
</div>
)
}
THIS THE NEW CODE WITH MULTIPLE BOXES:
What it's the best way if it's not with innerHTML to show the icon ONLY in clicked box, like in my code here
import { ImCross } from "https://cdn.skypack.dev/react-icons/im";
const App = () => {
const boxes = {
backgroundColor: '#000',
color: '#fff',
width: 120,
height: 120,
}
const symbol = {
color: '#fff',
textAlign: 'center',
fontSize: 50
}
const styles = {
display: 'grid',
gridTemplateColumns: 'repeat(3, 120px)',
gap: 10
}
const handleClickBoard = (e) => {
// Here, I'm gettin <div> of clicked box
const clickedBox = e.currentTarget;
// What should i do here to make the children
element of clicked element/box show the icon <ImCross />
// I only can achieve what I want by using this
clickedBox.querySelector('.symbol-on-board').innerHTML = 'X';
}
let component = [];
let key = 0;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
key++;
component.push(
{/* This the BOX that wrap the symbol */}
<div style={boxes} id={key} key={key} onClick={(e) => handleClickBoard(e)}>
{/* This is where i want the symbol to be shown */}
<div style={symbol} className='symbol-on-board'></div>
</div>
)
}
}
return (
<div style={styles}>
{component}
</div>
)
}
Upvotes: 1
Views: 1193
Reputation: 943193
JSX is not HTML. It gets transformed into a bunch of JavaScript calls by Babel before it goes near the browser.
Don't try to generate React code dynamically. Work with React. Make use of the features it provides, like state.
For example:
const [clicked, setClicked] = useState(false);
const clickHandler = () => { setClicked(current => !current); }
return (
<div>
<div onClick={clickHandler} style={box}>
<div className='symbol' style={symbol}>
{clicked ? <ImCross/> : "Not clicked yet" }
</div>
</div>
</div>
)
Re comment: A more complex example with multiple boxes.
const [data, setData] = useState([
{ name: "Alice", clicked: false },
{ name: "Bob", clicked: false },
{ name: "Chuck", clicked: false }
]);
return <div>{
data.map(person =>
<Person key={person.name} setData={setData} person={person} />
)
}</div>;
and then
const Person = ({setData, person}) => {
const clickHandler = () => {
setData(data => {
return data.map(item => {
if (item.name === person.name) {
return {
...person,
clicked: !person.clicked
};
}
return person;
})
});
}
return <div onClick={clickHandler}>
{person.clicked && <ImCross/>}
{person.name}
</div>
}
Upvotes: 3