javascript - React-更改this.state onClick使用array.map()呈現




reactjs (3)

我是React和Javascript的新手,很抱歉,如果這太基礎了。

我有一個Menu組件,可以在 onClick 上呈現動畫,然後將應用程序重定向到另一個路徑 /coffee

我想傳遞點擊(選中)的值來運行 this.state.select 並更新 this.state.select ,但我不知道如何,因為我在同一個 onClick 映射 this.state.coffees 中的所有項目事件。

我該怎麼做並將 this.state.select 更新為點擊的值?

我的代碼:

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);

我試過像這樣傳遞值:

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

像這樣:

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

或者:

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

但是 console.log(this.state.select) 顯示兩次嘗試都是' undefined '。

看來我用'c'傳遞了 Class

瀏覽器在重定向的uri上準確地顯示了我:

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

現在,如果我將映射的'c'傳遞給 {this.renderCoffee(c)} ,而不是 onClick 事件,我設法傳遞數組項。

但我需要傳遞的不是對象,而是點擊的值'c'到 this.gotoCoffee(c) ,然後更新 this.state.select

我該如何解決?


你的問題實際上差不多了。 我打賭你的狀態未定義的原因是由於 event 的短暫性質。 setState 是一個異步操作,並不總是立即發生。 通過直接關閉事件並允許函數正常進行,事件在狀態可以設置之前被釋放。 我的建議是將你的 gotoCoffee 函數更新為:

 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) 
  }

請注意,我將console.log行移動到setState中的回調函數,以便在AFTER狀態更新之前不會觸發它。 每次使用類組件並且需要在更新狀態後立即執行某些操作時,請使用回調函數。


因此,基於您的代碼,您可以通過幾種方式完成。

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

這看起來像你想要的方法。

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

c 將與數組中的項目相關。


所有答案看起來都沒問題並且對你有用,很明顯你沒有在點擊處理程序中傳遞正確的值而犯了一個錯誤。 但是既然你是這個時代的新手,我認為最好以這種方式改變你的實現:

  • 根本不需要使用構造函數,您可以使用初始值聲明一個state屬性:

    class Menus extends Component{
        state: {
            /* state properties */
        };
    }
  • 在render方法中聲明函數時,它總是會為每個渲染創建一個新的渲染,這個渲染具有一定的成本並且未進行優化。 如果你使用currying更好:

    handleClick = selected => () => { /* handle click */ }
    render () {
        // ...
        coffees.map( coffee =>
            // ...
             <div onClick={ this.handleClick(coffee) }>
            // ...
    }
  • 您可以使用 history.replace 重定向,因為您使用 withRouter 包裝了組件,這在此處有用,導致您重定向點擊並刪除 renderCoffee 方法:

    handleClick = selected => () => 
        this.setState(
            { isLoading: true},
            () => setTimeout(
                () => {
                    const { history } = this.props;
                    this.setState({ isLoading: false });
                    history.replace(`/${coffee}`);
                }
                , 5000)
        );

由於 Redirect 取代了路由,我認為您希望正常的頁面更改不替換我建議使用 history.push





reactjs