Как дать каждому элементу массива ссылку в Typescript?

У меня есть компонент, который отображает несколько объектов, один из которых — массив диапазонов.

Вот часть моего кода:

class MyComponent ... {
  private targetSpan = HTMLElement;

  componentDidMount() {
    //Here I get some data that fills an array that has 6 values
  }

   ...
   ...
   ...

  private setActive(value) {
    let target = this.targetSpan;

    if (target.classList.contains('active')) {
      target.classList.remove('active');
      //do more things
    }
    else {
      target.classList.add('active');
      //do even more things
    }
  }

  private splitMyThings() {
    const returnThings: any[] = [];

    forEach(array, thing => {
      returnThings.push(
        <span class = "thing" onClick = {() => this.setActive(thing)} ref = {elem => this.targetSpan = elem}>
          {thing}
        </span>
      );
    });
  }

  render() {
  ...

    return <div class = "container">
      ...
      <div class = "myTargets">
        {this.splitMyThings()}
      </div>
      ...
    </div>;
  }
}

Когда я смотрю результат в браузере, все диапазоны отображаются так, как я хочу, единственное, что, похоже, работает неправильно, это функция setActive (или даже что-то еще?). Независимо от того, какой диапазон я нажимаю, каждый раз, когда только последний получает активный класс, я совершенно не могу понять, как это исправить.

Надеюсь, у кого-то есть быстрое и простое решение или идея, как этого добиться. заранее спасибо!

Было бы проще использовать event.target в обработчике onClick вместо ссылки.

Unmitigated 26.07.2024 22:25

Вы устанавливаете this.targetSpan для каждого элемента, переопределяя назначение на каждой итерации. Я не совсем понимаю, как вы ожидаете, что это сработает?

rschristian 28.07.2024 03:01
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
0
2
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы пытаетесь изменить «вещь» с помощью функции setActive.

Но, глядя на setActive(value), вы на самом деле никогда ничего не делаете с value в этом контексте, а вместо этого извлекаете его из своего класса с помощью , а вместо этого извлекаете его из let target = this.targetSpan;

В этом контексте я использую «ценность» для некоторых других задач. Я даже попытался передать функции два параметра (это, значение), и в функции я говорю «let target = event.target», но она все равно не работает.

erniberni 27.07.2024 12:01
Ответ принят как подходящий

Вот пример того, как вам следует подходить к чему-то вроде этого:

import { Component, render } from 'preact';

const CSS_TEXT = `
    .thing {
        cursor: pointer;
    }

    .selected {
        color: red;
    };
`;

class MyComponent extends Component {
    state = {
        // index of the selected item -- if your list items can change, you'll want a better identifier, such as the text.
        selectedIdx: -1, 
        array: []
    }

    componentDidMount() {
        // Just creating an array as you mention in the post
        this.setState({ array: Array.from({ length: 6 }).map((_, i) => i) });
    }

    render() {
        return (
            <div>
                <style>{CSS_TEXT}</style>
                <ul>
                    {this.state.array.map((thing, i) => (
                        <li
                            class = {this.state.selectedIdx == i ? 'selected' : ''}
                            onClick = {() => this.setState({ selectedIdx: i })}
                        >
                            {thing}
                        </li>
                    ))}
                </ul>
            </div>
        );
    }
}

render(<MyComponent />, document.getElementById('app'));

Можно протестировать в Preact REPL

Ссылки не подходят, а DOM API не похожи на .classList. Вам также не следует использовать цикл forEach для перебора одного списка и заполнения другого — для этого и нужен .map.

Немного изменил ваш пример для лучшей демонстрации (сделав массив списком вместо диапазонов, добавив CSS для выбранных элементов), но его должно быть легко перевести обратно.

Большое спасибо за этот пример. Мне потребовалось довольно много времени (еще новичку), но теперь это работает!! :)

erniberni 30.07.2024 19:51

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