`id` elementu HTML musi być niepowtarzalny na całej stronie, jak to pogodzić z enkapsulacją komponentów?

`id` elementu HTML musi być niepowtarzalny na całej stronie, jak to pogodzić z enkapsulacją komponentów?
YA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 252
0

Mamy przykładowy komponent Reacta:

Kopiuj
class InputName extends React.Component {                                                          // machanie łopatą
    constructor(props) {                                                                           // ...
        super(props)                                                                               // ...
        this.onChange = this.onChange.bind(this)                                                   // ...
    }                                                                                              // ...
                                                                                                   // ...
    onChange(e) {                                                                                  // ...
        this.props.onChange(e.target.value)                                                        // ...
    }                                                                                              // machania łopatą koniec

    render() {                                                                                     // meritum problemu
        return (<span>                                                                             // ...
            <label htmlFor='inputName'>Please enter your name: </label>                            // ...
            <input id='inputName' value={this.props.value} onChange={this.onChange} />             // ...
        </span>)                                                                                   // ...
    }                                                                                              // tyle

(tak, wiem - tu da się ten problem obejść zawierając input w label i w ten sposób uniknąć konieczności użycia atrubutu id, ale nie zawsze tak się da)

Powyższy kod jest prawidłowy tylko wtedy, jeżeli żaden inny tag HTML na danej stronie nie będzie miał atrybutu id wynoszącego inputName. W szczególności komponent InputName nie może być dwukrotnie użyty.

Czy można to zakładać? Programista może o tym wiedzieć, ale czy "komponent" może o tym wiedzieć? O ile dobrze rozumiem enkapsulację, to komponent nie powinien zakładać, jak będzie użyty, inaczej mamy niepożądany tight coupling.

Rozwiązania tego problemu widzę dwa...

Po pierwsze, można w komponencie generować jakiś UUID i prefixować wartość atrybutu id tym UUID. Tak bym chciał zrobić, ale StackOverflow bardzo naciska, że nie wolno generować UUID za pomocą Math.random(), trzeba użyć kryptograficznie bezpiecznego generatora liczb pseudolosowych, a tak się składa, że jest on dostępny wyłącznie wtedy, gdy strona idzie po https, trudno więc zakładać, że zawsze będzie go można użyć.

Po drugie, można przyjmować jakiś prefiks w argumentach komponentu, wtedy niech kod, który tworzy nasz komponent, martwi się, by zduplikowanym komponentom dać różne prefiksy. Ale czy to jest szeroko przyjęte rozwiązanie? Bo jeśli nie, to będzie tylko konfudować ludzi.

Jak się najczęściej rozwiązuje tego rodzaju problemy?

mr_jaro
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Grudziądz/Bydgoszcz
  • Postów: 5300
0

Używać id tylko dla globalnego kontenera strony. W innym wypadku nie jest nigdy potrzebny.

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5618
0

Trzeba budować złożenie idki. Jak to nie wiem. Zawsze robiły to za mnie frameworki, ale rezultat był w rodzaju id=<cześć wygenerowane przez framework><cześć nadana przeze mnie>

Xarviel
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 848
0

Jeśli chcesz jedynie uniknąć duplikacji ID na stronie i nie potrzebujesz za każdym razem generować nowego identyfikatora to najprościej rozwiązać to przez props

Kopiuj
render() {                                                                                     
  return (
    <span>                                                                             
      <label htmlFor={this.props.inputID}>Please enter your name: </label>                        
      <input id={this.props.inputID} value={this.props.value} onChange={this.onChange} /> 
    </span>
  )                                                                                 
}  
Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10286
0

Odpowiedź @mr_jaro Jest najlepsza.

Inne odpowiedzi to próba obchodzenia nieistniejącego problemu.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.