Как изменить цвет полей в сетке

#javascript #html #reactjs #onclick #grid

Вопрос:

Я создал сетку с ячейками в ней, каждая из которых имеет идентификатор box i. Однако, когда я пытаюсь добавить функцию щелчка по кнопке, чтобы изменить цвет поля, это мне не позволяет. Вот код:

 function Board() {
    
    var rows = []
    var numrows = 1000;
    for(var i = 0; i < numrows; i  ){
        rows.push(<Box id={"box"   i}  tabIndex="0" onClick={
            document.getElementById(`box${i}`).style.backgroundColor = "red"

        } className="box"  />);
    }

    return (
       <GameBoard>
           {rows}
       </GameBoard>
    )
}
 

доска экспорта по умолчанию

Комментарии:

1. Что происходит? Вы видите ошибку в журналах? Какой цвет в начале и что происходит после нажатия? Эти сведения полезны, когда у нас нет доступа ко всему коду.

2. В нем говорится, что ошибка типа: document.getElementById(…) в журналах равен нулю. Цвета коробки белые и, как ожидается, станут красными при нажатии. Однако эта ошибка появляется еще до того, как я смогу нажать.

Ответ №1:

Вы можете установить a state в Box компоненте и переключить его локально:

 const { useState } = React

const Box = (props) => {
  const [boxStyle, setBoxStyle] = useState({})
  
  const toggleBackground = () => {
    if ('background' in boxStyle) {
      setBoxStyle({})
    } else {
      setBoxStyle({'background': 'red'})
    }
  }
  
  return (
    <div className="box" style={boxStyle} onClick={toggleBackground}>{props.id}</div>
  )
}

const GameBoard = (props) => {
  return (
    <div>
      { props.children }
    </div>
  )
}

const Board = () => {
  var rows = []
  var numrows = 10;
  for(var i = 0; i < numrows; i  ) {
    rows.push(<Box id={"box"   i} key={`key-${i}`} tabIndex="0" />);
  }
  return (
    <GameBoard>{ rows }</GameBoard>
  )
}

const domContainer = document.querySelector('#root');
ReactDOM.render(<Board />, domContainer); 
 .box {
  border: 1px solid black;
} 
 <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div> 

предложение:

Когда вы работаете с реактивной структурой, такой как React (или Vue), старайтесь избегать прямых манипуляций DOM. Эти фреймворки выполняют для вас большую работу, но довольно легко испортить их процессы, если вы измените что-то, что они не могут отследить.

Ответ №2:

onClick Опора Box должна быть функцией

 
<Box
 id={"box"   i}
 tabIndex="0"
 onClick={() => {
            document.getElementById(`box${i}`).style.backgroundColor = "red"
        }
 }
 className="box"
/>

 

PS: Не забудьте использовать реквизит id в фактическом элементе DOM, например, в определении компонента Box

 const Box = ({id, /*... rest props*/}) => {
   return (
      <div id={id}> {/* assign ID to real DOM node so it's accessible in document.getElementById*/}
       {/* rest of the Box component definition*/}
      </div>
 )
}
 

Комментарии:

1. Да, извините, я забыл добавить это в код, который я показал, но даже при этом он позволяет мне нажать на поле, которое меняет цвет так, как я хочу, но затем выдает: ошибка типа: документ.getElementById(…) равен нулю.

2. можете ли вы обновить код? Кроме того, если вы получаете document.getElementById(...) значение null, то идентификатор, который вы предоставляете, неверен. Отладчик браузера можно использовать для пошагового просмотра кода, чтобы увидеть, какой идентификатор передается, а затем просмотреть его на вкладке элементы, если оно существует.

3. вот поле codesandbox, которое работает поверх предоставленного вами кода. См. Компонент платы. codesandbox.io/s/async-flower-e3srz

4. Спасибо, это устраняет мою проблему, которую я пытался решить в течение некоторого времени. Я ценю это!

5. Без проблем. Я также согласен с другими ответами — то есть использовать крючки состояния вместо document.getElementById установки значения цвета. Потому что это правильный путь. Смешивать императивное программирование с декларативным программированием на самом деле не очень хорошая идея.

Ответ №3:

Использование document.getElementById не рекомендуется в react.

Ниже приведено представление крючков для вашего кода:

 function Row(){
    const [coloured,setColoured] = useState(false);
    const handleClick=()=>{
        setColoured(true)
    }
    return <Box style={coloured?{color:"red"}:null} tabIndex="0" onClick={handleClick} className="box"  />
}

function Board() {
    
    var numrows = 1000;
    var rows = new Array(numrows)

    return (
       <GameBoard>
           {rows.map(()=><Row />)}
       </GameBoard>
    )
}
 

Вы можете импортировать useState из react, т. е.

 import React, { useState } from 'react'
 

Комментарии:

1. Да, вы можете сделать любую коробку красной, просто нажав на них, потому что они находятся в разных компонентах, поэтому изменение состояния одной коробки не повлияет на состояние других коробок.