简体   繁体   中英

How to update styles dynamically in JSX

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

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

编辑分心的雪花-ngp4n

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM