Szukaj…


Stan podstawowy

Składniki State in React są niezbędne do zarządzania danymi w aplikacji i przekazywania ich. Jest reprezentowany jako obiekt JavaScript i ma zakres na poziomie komponentu , można go traktować jako prywatne dane komponentu.

W poniższym przykładzie definiujemy stan początkowy w funkcji constructor naszego komponentu i wykorzystujemy go w funkcji render .

class ExampleComponent extends React.Component {
  constructor(props){
    super(props);

    // Set-up our initial state
    this.state = {
      greeting: 'Hiya Buddy!'
    };
  }

  render() {
    // We can access the greeting property through this.state
    return(
      <div>{this.state.greeting}</div>
    );
  }
}

setState ()

Podstawowym sposobem dokonywania aktualizacji interfejsu użytkownika do aplikacji React jest wywołanie funkcji setState() . Ta funkcja wykona płytkie scalenie między nowym stanem, który podajesz, a poprzednim stanem, i uruchomi ponowne renderowanie twojego komponentu i wszystkich decedentów.

Parametry

  1. updater : Może to być obiekt z wieloma parami klucz-wartość, który powinien zostać scalony ze stanem, lub funkcja zwracająca taki obiekt.
  2. callback (optional) : funkcja, która zostanie wykonana po setState() wykonaniu setState() . Ponieważ React nie gwarantuje, że wywołania setState() mają charakter atomowy, może to czasem być przydatne, jeśli chcesz wykonać jakąś akcję po setState() że setState() został pomyślnie wykonany.

Stosowanie:

Metoda setState akceptuje argument updater który może być albo obiektem z wieloma parami klucz-wartość, które powinny zostać scalone w stan, lub funkcją, która zwraca taki obiekt obliczony z prevState i props .

Użycie setState() z Object jako updater

//
// An example ES6 style component, updating the state on a simple button click.
// Also demonstrates where the state can be set directly and where setState should be used.
//
class Greeting extends React.Component {
    constructor(props) {
        super(props);
        this.click = this.click.bind(this);
        // Set initial state (ONLY ALLOWED IN CONSTRUCTOR)
        this.state = {
            greeting: 'Hello!'
        };
    }
    click(e) {
        this.setState({
              greeting: 'Hello World!'
        });
    }
    render() {
        return(
            <div>
                <p>{this.state.greeting}</p>
                <button onClick={this.click}>Click me</button>
            </div>
        );
    }
    
}

Użycie setState() z funkcją jako updater

//
// This is most often used when you want to check or make use 
// of previous state before updating any values.
//

this.setState(function(previousState, currentProps) {
  return {
    counter: previousState.counter + 1
  };
});

Może to być bezpieczniejsze niż użycie argumentu obiektowego, w którym używanych jest wiele wywołań setState() , ponieważ wiele wywołań może być grupowanych razem przez React i wykonywane jednocześnie, i jest to preferowane podejście przy użyciu bieżących rekwizytów do ustawienia stanu.

this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 1 });

Wywołania te mogą być grupowane razem przez React za pomocą Object.assign() , w wyniku czego licznik jest zwiększany o 1 zamiast 3.

Podejście funkcjonalne można również wykorzystać do przeniesienia logiki ustawiania stanu poza komponenty. Pozwala to na izolację i ponowne wykorzystanie logiki stanu.

// Outside of component class, potentially in another file/module

function incrementCounter(previousState, currentProps) {
    return {
        counter: previousState.counter + 1
    };
}

// Within component

this.setState(incrementCounter);

Wywołanie setState() z Object i funkcją zwrotną

//
// 'Hi There' will be logged to the console after setState completes
//

this.setState({ name: 'John Doe' }, console.log('Hi there'));

Wspólne antipattern

Nie powinieneś zapisywać props do state . Jest uważany za anty-wzór . Na przykład:

export default class MyComponent extends React.Component {
    constructor() {
        super();

        this.state = {
            url: ''
        }

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

    onChange(e) {
        this.setState({
            url: this.props.url + '/days=?' + e.target.value
        });
    }

    componentWillMount() {
        this.setState({url: this.props.url});
    }

    render() {
        return (
            <div>
                <input defaultValue={2} onChange={this.onChange} />

                URL: {this.state.url}
            </div>
        )
    }
}

url prop jest zapisywany w state a następnie modyfikowany. Zamiast tego wybierz zapisanie zmian do stanu, a następnie zbuduj pełną ścieżkę, używając zarówno state jak i props :

export default class MyComponent extends React.Component {
    constructor() {
        super();

        this.state = {
            days: ''
        }

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

    onChange(e) {
        this.setState({
            days: e.target.value
        });
    }

    render() {
        return (
            <div>
                <input defaultValue={2} onChange={this.onChange} />

                URL: {this.props.url + '/days?=' + this.state.days}
            </div>
        )
    }
}

Wynika to z faktu, że w aplikacji React chcemy mieć jedno źródło prawdy - tj. Za wszystkie dane odpowiedzialny jest jeden element i tylko jeden element. Obowiązkiem tego komponentu jest przechowywanie danych w jego stanie i przekazywanie danych do innych komponentów za pomocą rekwizytów.

W pierwszym przykładzie zarówno klasa MyComponent, jak i jej rodzic utrzymują „url” w swoim stanie. Jeśli zaktualizujemy state.url w MyComponent, zmiany te nie zostaną odzwierciedlone w obiekcie nadrzędnym. Straciliśmy nasze jedyne źródło prawdy i coraz trudniej jest śledzić przepływ danych za pośrednictwem naszej aplikacji. Porównaj to z drugim przykładem - adres URL jest utrzymywany tylko w stanie komponentu nadrzędnego i wykorzystywany jako rekwizyt w MyComponent - dlatego utrzymujemy jedno źródło prawdy.

Stan, zdarzenia i kontrolowane elementy sterujące

Oto przykład komponentu React z „zarządzanym” polem wejściowym. Ilekroć zmienia się wartość pola wejściowego, wywoływana jest procedura obsługi zdarzeń, która aktualizuje stan komponentu o nową wartość pola wejściowego. Wywołanie setState w setState obsługi zdarzeń wyzwoli wywołanie w celu render aktualizacji komponentu w domenie.

import React from 'react';
import {render} from 'react-dom';


class ManagedControlDemo extends React.Component {

  constructor(props){
    super(props);
    this.state = {message: ""};
  }

  handleChange(e){
    this.setState({message: e.target.value});
  }

  render() {
    return (
      <div>
        <legend>Type something here</legend>
          <input 
            onChange={this.handleChange.bind(this)} 
            value={this.state.message} 
            autoFocus />
        <h1>{this.state.message}</h1>
      </div>
   );
  } 
}


render(<ManagedControlDemo/>, document.querySelector('#app'));

Bardzo ważne jest zwrócenie uwagi na zachowanie środowiska wykonawczego. Za każdym razem, gdy użytkownik zmienia wartość w polu wprowadzania

  • handleChange zostanie wywołany i tak
  • zostanie setState i tak dalej
  • render zostanie wywołany

Pop quiz, po wpisaniu znaku w polu wprowadzania, które elementy DOM zmieniają się

  1. wszystkie z nich - div najwyższego poziomu, legenda, wejście, h1
  2. tylko wejście i h1
  3. nic
  4. co to jest DOM?

Możesz eksperymentować z tym więcej tutaj, aby znaleźć odpowiedź



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow