Űrlapok

A HTML űrlap elemek kissé máshogy működnek a többi DOM elemhez képest Reactben, mert az űrlap elemek alapvetően egy saját belső állapotot tartanak nyilván. Például ez az űrlap szimpla HTML-ben egy nevet fogad be:

<form>
  <label>
    Név:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="Submit" />
</form>

Amikor a felhasználó beküldi ezt az űrlapot, a HTML alapviselkedése miatt ez egy új oldalra fog navigálni. Ha ezt a viselkedést szeretnéd elérni Reactben, eleve működni fog. De a legtöbb esetben érdemesebb egy JavaScript függvényben lekezelni az űrlap beküldését, aminek hozzáférése van a felhasználó által bevitt adatokhoz. Ennek elérése általában az úgynevezett “kontrollált komponensek” módszerével lehetséges.

Kontrollált komponensek

A HTML űrlap elemek, mint az <input>, <textarea> és <select>, általában fenntartják a saját belső állapotukat, amit felhasználói bevitel alapján változtatnak. A Reactben a módosítható állapotot általában a komponens állapotában tároljuk, és csak a setState() meghívásával változik.

Ezt a kettőt összekombinálhatjuk ha a React állapotot vesszük az “egyedüli igazságforrás”-ként. Így a React komponens, ami az űrlapot rendereli, azt is kontrollálja, hogy mi történik az űrlapban a felhasználói bevitel hatására. Egy beviteli elem, aminek az értékét ily módon a React kontrollál, “kontrollált komponens”-nek hívjuk.

Például ha azt szeretnénk hogy az előző példa kiírja a konzolra a nevet az űrlap beküldésekor, létrehozhatjuk az űrlapot egy kontrollált komponensként:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {    this.setState({value: event.target.value});  }
  handleSubmit(event) {
    alert('Ezt a nevet küldték be: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Név:
          <input type="text" value={this.state.value} onChange={this.handleChange} />        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Próbáld ki CodePenen

Mivel a value attribútum be van állítva az elemen, a megjelenített érték mindig this.state.value lesz, ez teszi a React állapotot az egyéni igazságforrássá. Mivel a handleChange minden egyes billentyűleütéskor frissíti a React állapotot, a megjelenített érték is frissülni fog a felhasználó bevitele eredményeképpen.

Egy kontrollált komponensben minden állapotmódosításhoz hozzá kell rendelni egy eseménykezelő függvényt. Ez egyszerűvé teszi a felhasználó által bevitt adat módosítását vagy érvényesítését. Például ha szeretnénk biztosítani, hogy a nevek csupa nagybetűvel legyenek írva, így módosíthatjuk a handleChange-t:

handleChange(event) {
  this.setState({value: event.target.value.toUpperCase()});}

Egy kontrollált komponensben a bemenet értékét mindig a React állapot vezérli. Habár ez azt jelenti, hogy egy kicsivel több kódot kell írnod, de így ezt az értéket több komponensnek is át tudod adni, vagy eseménykezelőkből a kezdeti állapotba állítani.

A textarea címke

A HTML-ben a <textarea> tartalma a gyermeke által van definiálva:

<textarea>
  Hellóka, ez itt némi szöveg egy szövegterületen
</textarea>

Reactben a <textarea> ehelyett egy value attribútumot használ. Így az űrlap, ami <textarea>-t használ, nagyon hasonló az egysoros beviteli mezőhöz:

class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {      value: 'Írj egy esszét a kedvenc DOM elemedről.'    };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {    this.setState({value: event.target.value});  }
  handleSubmit(event) {
    alert('Beküldtek egy esszét: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Esszé:
          <textarea value={this.state.value} onChange={this.handleChange} />        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Figyeld meg, hogy a this.state.value a konstruktorban kerül inicializálásra, így a szövegterület már az elején tartalmazni fog némi szöveget.

A select címke

A HTML-ben a <select> egy legördülő menüt hoz elő. Ez a HTML például egy ízesítésekből álló legördülő menüt tartalmaz:

<select>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Kókusz</option>
  <option value="mango">Mangó</option>
</select>

Figyeld meg, hogy a Kókusz opció van kiválasztva alapból, mivel ez tartalmazza a selected attribútumot. A React a selected attribútum helyett a value attribútumot használja a gyökér select címkén. Ez így egyszerűbb egy kontrollált komponensben, mivel így csak egy helyen kell módosítani az értéket. Például:

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {    this.setState({value: event.target.value});  }
  handleSubmit(event) {
    alert('Your favorite flavor is: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Válaszd ki a kedvenc ízesítésedet:
          <select value={this.state.value} onChange={this.handleChange}>            <option value="grapefruit">Grapefruit</option>
            <option value="lime">Lime</option>
            <option value="coconut">Kókusz</option>
            <option value="mango">Mangó</option>
          </select>
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Próbáld ki CodePenen

Alapvetően ezáltal mind az <input type="text">, <textarea> és <select> is hasonlóan működik - mindegyiknek van egy value attribútuma, amit használhatsz egy kontrollált komponens létrehozásához.

Megjegyzés

Ha egy tömböt rendelsz a value attribútumhoz, akár több opciót is kiválaszthatsz egyszerre a select címkében:

<select multiple={true} value={['B', 'C']}>

A fájlbeviteli címke

A HTML-ben az <input type="file"> segítségével a felhasználó kiválaszthat egy vagy több fájlt a saját gépéről a szerverre feltöltéshez vagy a JavaScript Fájl API-val való manipuláláshoz.

<input type="file" />

Mivel ez csak olvasható értékkel rendelkezik, ez egy kontrollálatlan komponens. Erről a többi kontrollálatlan komponenssel együtt olvashatsz később a dokumentációban.

Több bemenet kezelése

Ha több kontrollált input elemet is kezelned kell, hozzáadhatsz egy name attribútumot az egyes elemekhez, így az eseménykezelő függvény az event.target.name alapján tudja eldönteni, hogy mit csináljon.

Például:

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;
    this.setState({
      [name]: value    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

Próbáld ki CodePenen

Figyeld meg, hogy hogyan használtuk az ES6 kiszámított mező név szintaxist, hogy frissíteni tudjuk az állapotkulcsot, ami a megadott bemenet nevével egyezik meg:

this.setState({
  [name]: value});

Ez ekvivalens a következő ES5 kóddal:

var partialState = {};
partialState[name] = value;this.setState(partialState);

Valamint, mivel a setState() automatikusan összefésüli a részleges állapotot a jelenlegi állapottal, elég csak a megváltozott állapotot átadni.

Kontrollált bemenet null értéke

A value megadása egy kontrollált komponensen megakadályozza a felhasználót abban, hogy az engedélyünk nélkül változtassa meg a beviteli adatokat. Ha megadtál egy value-t, de a bemenet mégis szerkeszthető, valószínűleg véletlenül undefined vagy null-ra állítottad a value-t.

A következő kódrészlet ezt demonstrálja. (A bemenet eleinte nem szerkeszthető, de egy rövid késleltetés után szerkeszthetővé válik.)

ReactDOM.render(<input value="hi" />, mountNode);

setTimeout(function() {
  ReactDOM.render(<input value={null} />, mountNode);
}, 1000);

Kontrollált komponens alternatívák

Néha nehézkes lehet kontrollált komponenseket használni, mivel minden lehetséges adatváltoztatási módhoz kell egy eseménykezelőt írnod és hozzá kell kötni az összes belső állapotot a React komponens állapotához. Ez különösen bosszantó lehet, amikor meglévő kódot kell átírni Reactbe, vagy amikor egy nem React-alapú könyvtárat kell egy React applikációba integrálni. Ezekben az esetekben érdekes lehet a kontrollálatlan komponensek használata, az űrlap bementek egy alternatív implementációs módszere.

Teljes értékű megoldás

Ha egy meglévő teljes értékű megoldást keresel, amiben már benne van a validáció, a meglátogatott mezők nyomon követése és az űrlap beküldésének kezelése, a Formik az egyik legnépszerűbb választás. Ugyanakkor ez is hasonló alapelvekre épül, mint a kontrollált komponensek vagy az állapotmenedzsment - így ne felejtsd el ezeket sem megtanulni.

Is this page useful?Az oldal szerkesztése