Как использовать одну и ту же функцию для разных элементов в react?

Как я могу использовать одну и ту же функцию для преобразования разных элементов? Могу ли я использовать что-то вроде this.target и т. д.?

У меня есть пример, когда я хотел переместить компонент Box, когда я нажимал кнопку Move Box. Но теперь, какую бы кнопку я ни нажимал, будет преобразован только первый Box ...

const handleChangePos = () => {
  let box = document.getElementById("box");
  box.style.transform = `translateY(-20px)`;
};

const n = 4;

function App() {
    return (
      <div className="App">
        <h1>Hero</h1>
        <HeroBox>
            <Box id="box" />
            <button onClick={handleChangePos}>Move Box</button>
        </HeroBox>

        <h2>Sub Hero</h2>
        <SubHeroContainer>
        {[...Array(n)].map((e, i) => (
            <SubHeroBox key={i}>
                <Box2 id="box" />
                <button onClick={handleChangePos}>Move Box</button>
            </SubHeroBox>
        ))}
        </SubHeroContainer>
     </div>
);}

Живой пример: https://codesandbox.io/s/6vxqlo06v3

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

0
0
367
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам необходимо создать новый компонент, который будет включать в себя нужную вам функциональность. С React вам никогда не нужно звонить document.getElementById

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

https://codesandbox.io/s/3vn642j63m

Вот соответствующий компонент, если ссылка умирает:

class Moveable extends React.Component {
  constructor() {
    super();
    this.state = { offset: 0 };
    this.move = this.move.bind(this);
  }
  move() {
    if (this.state.offset === 0) {
      this.setState({ offset: -20 });
    } else {
      this.setState({ offset: 0 });
    }
  }
  render() {
    return [
      <Box2 id="box" style={{transform: `translateY(${this.state.offset}px)`}} />,
      <button onClick={this.move}>Move Box</button>
    ];
  }
}
Ответ принят как подходящий

Вы можете легко решить эту проблему несколькими способами, но, во-первых, у вас не должно быть нескольких элементов с одним и тем же идентификатором. Поскольку у вас уже есть id="Box" для заголовка, я предлагаю сгенерировать остальное с помощью индексов:

 <SubHeroContainer>
        {[...Array(n)].map((e, i) => (
            <SubHeroBox key={i}>
                <Box2 id={`box-${i}`} />
                <button onClick={() => handleChangePos(i)}>Move Box</button>
            </SubHeroBox>
        ))}
 </SubHeroContainer>

Затем вы можете изменить handleChangePos, чтобы принять параметр (индекс) и найти данный элемент:

const handleChangePos = (index) => {
  let box = document.getElementById(index ? `box-${index}` : "box");
  box.style.transform = `translateY(-20px)`;
};

Чтобы избежать передачи индекса, вы также можете использовать event.target.name из события, передаваемого кнопками при нажатии на них, и объявить кнопку как <button onClick={handleChangePos} name={i} >Move Box</button>, но почти то же самое.

Я также предлагаю не использовать идентификаторы, а поддерживать список refs и изменять их на основе индекса. Вы можете прочитать больше о рефах здесь: https://reactjs.org/docs/refs-and-the-dom.html

Поскольку я делаю это для компонента без состояния, поэтому я использовал ID. Ссылки нельзя использовать в апатридах, верно?

pizza0502 10.09.2018 08:32

Я обновил пример кода ссылки, и он работает с вашим решением. Но я не могу преобразовать первый элемент второй строки, когда я щелкнул по нему, преобразовался элемент первой строки. Я думаю, это потому, что идентификатор первого элемента второй строки равен нулю ... Не уверен в способе event.target.name, попробовал, но не удалось ... не могли бы вы привести мне пример? Благодарность!!!

pizza0502 10.09.2018 08:35

Вы правы, ссылки не могут использоваться с компонентами без состояния, однако я бы предложил использовать в вашем случае компонент с полным состоянием, имея только небольшие подкомпоненты в качестве компонентов без состояния, таких как Box и SubHeroContainer.

Ankari 10.09.2018 08:43

ах, я преобразовал 1-й элемент 2-й строки с помощью let box = document.getElementById(index === undefined ? "box-main" : box - $ {index} );

pizza0502 10.09.2018 09:00

Вы можете обрабатывать первую строку аналогично первой, вы также можете назвать ее box-0, а также использовать ее обработчик событий, например ()=>handleChangePos(0). Тогда вам не понадобится логика в функции обработчика, чтобы проверить, не определен ли индекс. Он должен хорошо работать.

Ankari 10.09.2018 09:07

Другие вопросы по теме