javascript - Reagisci-cambia this.state onClick reso con array.map()




reactjs (3)

In realtà ce l'hai quasi nella tua domanda. Scommetto che il motivo per cui il tuo stato non è definito è dovuto alla natura di breve durata event . setState è un'azione asincrona e non si verifica sempre immediatamente. Trasmettendo l'evento direttamente e consentendo alla funzione di procedere normalmente, l'evento viene rilasciato prima di poter impostare lo stato. Il mio consiglio sarebbe di aggiornare la tua funzione gotoCoffee a questo:

 gotoCoffee = (e) => {
    const selectedCoffee = e.target.value
    this.setState({isLoading:true,select:selectedCoffee},() => 
     {console.log(this.state.select})
    setTimeout(()=>{
      this.setState({isLoading:false,redirect:true})
    },5000) 
  }

Si noti che ho spostato la riga console.log in una funzione di richiamata all'interno di setState in modo che non venga attivata fino a quando lo stato AFTER non viene aggiornato. Ogni volta che si utilizza un componente di classe e si deve fare qualcosa subito dopo l'aggiornamento dello stato, utilizzare la funzione di callback.

Sono nuovo di React e Javascript, quindi mi dispiace se questo è troppo semplice.

Ho un componente Menu che esegue il rendering di un'animazione su onClick e quindi reindirizza l'app su un altro percorso, /coffee .

Vorrei passare il valore su cui è stato fatto clic (selezionato) per funzionare this.gotoCoffee e aggiornare this.state.select , ma non so come, poiché sto mappando tutti gli elementi in this.state.coffees nello stesso onClick evento.

Come posso fare questo e aggiornare this.state.select al valore cliccato?

Il mio codice:

class Menus extends Component{
  constructor (props) {
    super(props);
    this.state = { 
        coffees:[],
        select: '',      
        isLoading: false,
        redirect: false
    };
  };
  gotoCoffee = () => {
    this.setState({isLoading:true})
    setTimeout(()=>{
      this.setState({isLoading:false,redirect:true})
    },5000)
  }

  renderCoffee = () => {
    if (this.state.redirect) {
      return (<Redirect to={`/coffee/${this.state.select}`} />)
    }
  }

  render(){
    const data = this.state.coffees;

    return (
      <div>
        <h1 className="title is-1"><font color="#C86428">Menu</font></h1>
        <hr/><br/>
        {data.map(c => 
          <span key={c}>
            <div>
               {this.state.isLoading && <Brewing />}
               {this.renderCoffee()}
              <div onClick={() => this.gotoCoffee()} 
                  <strong><font color="#C86428">{c}</font></strong></div>
            </div>
          </span>)
        }
      </div>
    );
  }
}

export default withRouter(Menus);

Ho provato a passare il valore in questo modo:

  gotoCoffee = (e) => {
    this.setState({isLoading:true,select:e})
    setTimeout(()=>{
      this.setState({isLoading:false,redirect:true})
    },5000) 
    console.log(this.state.select)
  }

un così:

<div onClick={(c) => this.gotoCoffee(c)} 

o giù di lì:

<div onClick={(event => this.gotoCoffee(event.target.value} 

ma console.log(this.state.select) mi mostra " undefined " per entrambi i tentativi.

Sembra che sto passando la Class con 'c'.

il browser mi mostra esattamente quello sull'URI al reindirizzamento:

http://localhost/coffee/[object%20Object]

Ora se passo 'c' mappato su {this.renderCoffee(c)} , che non è un evento onClick , riesco a passare gli elementi dell'array.

ma non ho bisogno di passare l'oggetto, ma il valore cliccato 'c' a this.gotoCoffee(c) , e quindi aggiornare this.state.select .

come posso risolvere questo problema?


Puoi passare l' index dell'elemento a gotoCoffee con la chiusura in render . Quindi in gotoCoffee , accedi a quell'elemento come this.state.coffees[index] .

gotoCoffee = (index) => {
    this.setState({isLoading:true, select: this.state.coffees[index]})
    setTimeout(()=>{
      this.setState({isLoading:false,redirect:true})
    },5000)
  }

  render(){
    const data = this.state.coffees;

    return (
      <div>
        <h1 className="title is-1"><font color="#C86428">Menu</font></h1>
        <hr/><br/>
        {data.map((c, index) => 
          <span key={c}>
            <div>
               {this.state.isLoading && <Brewing />}
               {this.renderCoffee()}
              <div onClick={() => this.gotoCoffee(index)} 
                  <strong><font color="#C86428">{c}</font></strong></div>
            </div>
          </span>)
        }
      </div>
    );
  }
}

quindi in base al tuo codice potresti farlo in un paio di modi.

onClick=(event) => this.gotoCoffee(event.target.value)

Questo sembra l'approccio che desideri.

onClick=() => this.gotoCoffee(c)

c sarebbe correlato al tuo articolo nella matrice.





reactjs