Notă: Începând cu React 16, componentWillReceiveProps() este depreciat, adică dacă utilizați acea versiune sau o versiune superioară în proiectul dvs., acesta nu este un sfat bun pentru dvs.

În lumea React, forțarea unei redări este mal văzută. Ar trebui să lăsați DOM să aibă grijă de sine când React percepe modificări state sau props. Pentru a urma aceste tipare, uneori trebuie să facem lucruri care par puțin cam proste. Luați în considerare acest scenariu:

Cum sa reimprospatati fortat o componenta copil React modul usor
Exemplu simplu și prostesc de componentă copil care își gestionează propria stare

Avem două componente – un părinte și un copil. Părintele efectuează un apel API pentru a prelua fișierul user. Din aceasta, obținem lucruri de genul name, age, favorite color. Primim și un id din baza noastră de date. Vom transmite acest lucru componentei noastre copil, care va efectua, de asemenea, un apel API, cu ID-ul utilizatorului. Minunat – o mulțime de date intră în aplicația noastră.

Să presupunem că stocăm o listă de pantofi în baza de date. Când utilizatorul își modifică preferința de culoare, serverul scrie date noi în lista de pantofi a utilizatorului. Grozav! Cu excepția faptului, nu vedem noua listă de pantofi în componenta noastră pentru copii. Ce dă?

Notă marginală: Desigur, ar trebui să obținem pantofii din apelul pentru utilizator – aceasta este doar o explicație simplificată.

Reacționați noțiunile de bază privind redarea

Scurtul lucru este că React va actualiza doar părți din DOM care s-au schimbat. În acest caz, props trecem la componenta pantofului ( userId) nu s-au schimbat, deci nimic nu se schimbă în componenta noastră copil.

Preferința de culoare pentru utilizator se va actualiza atunci când primim informații noi din API – presupunând că facem ceva cu răspunsul după ce actualizăm un utilizator.

Dar, deoarece React nu vede niciun motiv să actualizeze lista de pantofi, nu o va face – chiar dacă pe serverul nostru, pantofii sunt acum diferiți.

Codul de pornire

const UserShow extends Component {
  state = {
    user: {}
  }
  
  componentDidMount() {
    this.fetchUser().then(this.refreshUser)
  }
  
  setNewColor = color => {
    this.updateUser({color}).then(this.refreshUser)
  }
  
  refreshUser = res => this.setState({user: res.data.user})
  
  render() {
    const { user } = this.state;
    
    return (
      <div>
        User name: {user.name}
        Pick color: 
        <div>
          {colors.map(color => 
            <div className={color} 
                 onClick={() => this.setNewColor(color)} />)}
          )}
        </div>
        <ShoeList id={user.id} />
      </div>
    )
  }
}

Al nostru ShoeList va fi doar o listă de pantofi, pe care o vom prelua de la server cu ID-ul utilizatorului:

const ShoeList extends Component {
  state = {
    shoes: []
  }
  
  componentDidMount() {
    this.fetchShoes(this.props.id)
        .then(this.refreshShoeList)
  }

  refreshShoeList = res => this.setState({ shoes: res.data.shoes })
  
  render() {
    // some list of shoes
  }
}

Dacă dorim ca componenta pantofului să capteze noua listă de pantofi, trebuie să actualizăm elementele de recuzită pe care i le trimitem. În caz contrar, nu va fi nevoie să reîmprospătați.

De fapt, modul în care este scris acest lucru, ShoeList nu s-ar reîmprospăta niciodată, deoarece nu suntem dependenți de recuzită pentru redare. Să remediem asta.

Declanșarea unei componente secundare pentru redare

Pentru a forța componenta secundară să redea redarea – și pentru a efectua un nou apel API – va trebui să trecem un element propice care se va schimba dacă preferința de culoare a utilizatorului s-a modificat.

Pentru a face acest lucru, vom adăuga o metodă în setNewColor:

[...]

setNewColor = color => {
  this.updateUser({color}).then(res => {
    this.refreshUser(res);
    this.refreshShoeList();
  })
}

refreshShoeList = () => 
  this.setState({refreshShoeList: !this.state.refreshShoeList})
  
[...]

<ShoeList id={user.id} refresh={refreshShoeList}

Acesta este un simplu comutator pe care îl putem roti. Am păstrat lucrurile cât mai simple posibil, dar în producție am vrea să ne asigurăm că culoarea pe care o setăm este diferită de cea pe care o aveam înainte. În caz contrar, nu va fi nimic de actualizat.

Acum în ShoeList:

componentWillReceiveProps(props) {
  const { refresh, id } = this.props;
  if (props.refresh !== refresh) {
    this.fetchShoes(id)
      .then(this.refreshShoeList)
  }
}

Dacă treci doar refreshShoeList și apoi comutați pe baza acelui boolean, componenta se va actualiza pur și simplu în vecii vecilor.

Trebuie să ne asigurăm că comutatorul a răsturnat o singură dată – așa că vom verifica doar dacă accesoriile care vin sunt diferite de cele pe care le aveam înainte. Dacă acestea sunt diferite, vom efectua un nou apel API pentru a obține noua listă de pantofi.

Și boom – componenta copilului nostru a fost „forțată” să se actualizeze.

componentWillReceiveProps

Merită să mai luăm doar un minut pentru a trece în revistă ce se întâmplă în ultima bucată de cod. În componentWillReceiveProps avem singura noastră oportunitate de a vizualiza recuzită nouă pe măsură ce intră și de a le compara cu recuzita anterioară.

Aici putem detecta modificările (ca în refresh) și putem face, de asemenea, verificări pentru accesorii noi (rețineți, de exemplu, că refresh este inițial undefined).

Această metodă React este un mod foarte puternic de manipulare și examinare props.