TransWikia.com

How to update styles dynamically in JSX

Stack Overflow Asked by nomalts on December 7, 2021

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'));

3 Answers

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'));

Answered by Mahdi mehrabi on December 7, 2021

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';
}  

Answered by bitDaft on December 7, 2021

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)}
        />
      ))}
    </>
  );
};

Edit distracted-snowflake-ngp4n

Answered by Dennis Vash on December 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP