反应-更改使用array.map()呈现的this.state onClick

dat*_*den 12 javascript reactjs

我是React和Java语言的新手,如果这太基础了,请抱歉。

我有一个Menu组件,该组件呈现动画onClick,然后将应用程序重定向到另一条路线/coffee

我想传递被单击(选择)的值以进行功能this.gotoCoffee和更新this.state.select,但我不知道如何进行操作,因为我正在this.state.coffees同一onClick事件中映射所有项目。

我该怎么做并更新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);
Run Code Online (Sandbox Code Playgroud)

我试图像这样传递值:

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

像这样:

<div onClick={(c) => this.gotoCoffee(c)} 
Run Code Online (Sandbox Code Playgroud)

或者:

<div onClick={(event => this.gotoCoffee(event.target.value} 
Run Code Online (Sandbox Code Playgroud)

但是两次尝试都console.log(this.state.select)向我显示“ undefined”。

看来我Class用'c' 传递了。

浏览器精确地向我显示了在uri上的重定向:

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


现在,如果将映射的'c'传递给{this.renderCoffee(c)},而不是onClick事件,那么我将设法传递数组项。

但是我需要传递的不是对象,而是单击的值'c' this.gotoCoffee(c),然后更新this.state.select

我该如何解决?

muk*_*210 8

您可以index在中gotoCoffee使用闭包将元素传递给render。然后进入gotoCoffee,只需访问该元素即可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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Mor*_*ani 5

所有答案看起来都不错,并且对您有用,很明显,您没有在点击处理程序中传递正确的值就犯了一个错误。但是由于您是这个时代的新手,所以我认为最好以这种方式更改实现:

  • 根本不需要使用构造函数,您可以使用初始值声明一个state属性:

    class Menus extends Component{
        state: {
            /* state properties */
        };
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 当您在render方法中声明函数时,它总是为每个渲染创建一个新的渲染,这会花费一些成本并且没有进行优化。最好使用curring:

    handleClick = selected => () => { /* handle click */ }
    render () {
        // ...
        coffees.map( coffee =>
            // ...
             <div onClick={ this.handleClick(coffee) }>
            // ...
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 您可以使用进行重定向,history.replace因为您用包裹了您的组件,withRouter这在这里很有用,因为这会导致单击时进行重定向并摆脱renderCoffee方法:

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

由于Redirect替换路由,我认为您希望正常的页面更改不替换,因此我建议history.push改用。