Reputation: 41
I am trying to update the individual style of each button when it is clicked, using the useRef()
hook from React.
Right now, when I click any button the style change is always applied to the last button rendered.
I believe this is the bit needing attention but I'm stumped.
const handleClick = () => {
status.current.style.background = 'green';
}
Here's the full bit:
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
let background = 'blue';
let controls = [];
const makeControls = () => {
for (let i = 1; i <= 9; i++) {
controls.push({active: false});
}
return controls;
};
const ControlPanel = () => {
const status = useRef('blue');
makeControls();
const handleClick = () => {
status.current.style.background = 'green';
}
return (
<>
{controls.map((control, i) => (
<div
ref={status}
style={{background: background}}
className={'box'}
key={i}
onClick={() => handleClick()}></div>
))}
</>
);
};
ReactDOM.render(<ControlPanel />, document.getElementById('root'));
Upvotes: 1
Views: 105
Reputation: 1744
you can use state to do that like this
import React, { useRef,useState } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
let controls = [];
const makeControls = () => {
for (let i = 1; i <= 9; i++) {
controls.push({active: false});
}
return controls;
};
const ControlPanel = () => {
const [controlState,setControlState]=useState({background:"blue"})
const status = useRef('blue');
makeControls();
const handleClick = () => {
setControlState({background:"green"});
}
return (
<>
{controls.map((control, i) => (
<div
ref={status}
style={{background: controlState.background}}
className={'box'}
key={i}
onClick={() => handleClick()}></div>
))}
</>
);
};
ReactDOM.render(<ControlPanel />, document.getElementById('root'));
Upvotes: 0
Reputation: 177
When rendering the list of <div>
s your status
ref is getting reassigned each time, finally stopping on the last element.
which is why the last element gets updated.
Instead why not store the background color info on the control object itself
for (let i = 1; i <= 9; i++) {
controls.push({active: false,background: 'blue'});
}
{controls.map((control, i) => (
<div
style={{background: control.background}}
className={'box'}
key={i}
onClick={() => handleClick(control)}></div>
))}
const handleClick = (control) => {
control.background = 'green';
}
Upvotes: 0
Reputation: 53884
Currently, your ref
targets only the last item, you should target all your control items by making an array of refs.
let controls = [];
const makeControls = () => {
for (let i = 1; i <= 9; i++) {
controls.push({ active: false });
}
return controls;
};
makeControls();
const ControlPanel = () => {
const status = useRef([]);
const handleClick = index => {
status.current[index].style.background = 'green';
};
return (
<>
{controls.map((control, i) => (
<div
ref={ref => (status.current[i] = ref)}
style={{ background: `blue`, width: 100, height: 100 }}
key={i}
onClick={() => handleClick(i)}
/>
))}
</>
);
};
Upvotes: 1