无法使用array.map

时间:2017-08-01 10:10:54

标签: javascript reactjs reactive-programming

我有一个组件,只需点击一下按钮即可显示图像。当这些图像显示在屏幕上时,我想对它们应用onClick监听器,以便我点击的图像显示在整个屏幕上。

代码:

class App extends React.Component{
  constructor(props){
    super(props);
    this.state={
      images:[],
      pano:'',
      name:'',
      list:[]
    }
    this.loadImages=this.loadImages.bind(this);
    this.loadOne=this.loadOne.bind(this);
  }


  loadImages(){
    console.log("load");
    var that=this;
    $.ajax({
      type:'GET',
      url:'https://demo0813639.mockable.io/getPanos',
      success:function(result){
        var images=that.state.images;
        for(var i=0;i<result.length;i++){
          that.state.images.push({"pano":result[i].pano,"name":result[i].name});
        }
        that.setState({
          images:images
        })
      }
    })
  }

  loadOne(url){
     console.log("hi")
  }


  render(){  
    var list=this.state.list;
    list=this.state.images.map(function(result){
      //console.log(result.name);
      return(<div className="box">
        <div className="label">{result.name}</div>
            <img src={result.pano} className="image"/>   
        </div>
      )
    })
    return( 
      <div>
        <button onClick={this.loadImages}>Click</button>
        <div onClick={this.loadOne(this,this.props.result.pano)}>{list}</div>      
      </div>
    );
  }
}

loadOne()是单击图像后调用的函数。我收到错误:

  

无法读取未定义的属性全局

如果我喜欢这样:

render(){
  var list=this.state.list;
  list=this.state.images.map(function(result){
    return(<div className="box">
        <div className="label">{result.name}</div>
          <img src={result.pano} className="image" onClick={this.loadOne(this,this.props.result.pano)}/>   
      </div>
    )
  })

  return( 
    <div>
      <button onClick={this.loadImages}>Click</button>
      <div >{list}</div>      
    </div>
  );
}

然后我收到错误:

  

无法读取未定义的属性loadOne。

那么,我怎样才能将特定的图片网址传递给我的函数?

2 个答案:

答案 0 :(得分:3)

第二个代码段的问题是:

1-您忘记绑定地图回调方法,请使用arrow function

var list = this.state.list;
list = this.state.images.map((result) => {   //here
    .....

2-你错过​​了这里的bind字词:

onClick = {this.loadOne.bind(this,result.pano)}

3-而不是this.props.result.pano它应该是result.pano

完整代码:

var list = this.state.list;
list = this.state.images.map((result) => {
    return(
        <div className="box">
            <div className="label">{result.name}</div>
            <img src={result.pano} className="image" onClick={this.loadOne.bind(this,result.pano)}/>   
        </div>
    )
})

工作代码:

&#13;
&#13;
class App extends React.Component{
  constructor(props){
    super(props);
    this.state={
      images:[],
      pano:'',
      name:'',
      list:[]
    }
    this.loadImages=this.loadImages.bind(this);
    this.loadOne=this.loadOne.bind(this);
  }
 
 
  loadImages(){
    var that=this;
    $.ajax({
      type:'GET',
      url:'https://demo0813639.mockable.io/getPanos',
      success:function(result){
        var images=that.state.images;
        for(var i=0;i<result.length;i++){
          that.state.images.push({"pano":result[i].pano,"name":result[i].name});
        }
        that.setState({
          images:images
        })
      } 
    })
  }
 
  loadOne(pano){
    console.log('pano', pano);
  }
 
 
  render(){
    var list = this.state.list;
    list = this.state.images.map((result)=>{
    return(
        <div className="box">
          <div className="label">{result.name}</div>
            <img src={result.pano} className="image" onClick={this.loadOne.bind(this,result.pano)}/>  
        </div>
      )
    })
    return(
      <div>
        <button onClick={this.loadImages}>Click</button>
        <div >{list}</div>      
      </div>
    );
  }
}
 
ReactDOM.render(<App/>,document.getElementById('container'));
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='container'/>
&#13;
&#13;
&#13;

检查此答案:Why is JavaScript bind() necessary?

答案 1 :(得分:0)

您需要将单击功能绑定到该图像。

    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                images: [],
                pano: '',
                name: '',
                list: []
            }
            this.loadImages = this.loadImages.bind(this);
            //The loadOne cant be bound to this here, it needs a 
            //bind for each image. Effectivly creating one version of loadOne per image.  
        }

        loadImages() {
            $.ajax({
                type: 'GET',
                url: 'https://demo0813639.mockable.io/getPanos',
                success:(result) => {
                    var images = this.state.images;
                    for (var i = 0; i < result.length; i++) {
                        this.state.images.push({ url: result[i].pano, name: result[i].name });
                    }
                    this.setState({
                        images: images
                    })
                }

            })
        }

        loadOne(url, mouseEvent) {
          console.log(url);
        } 


        render() {
            //This can get extracted to a custom component
            var imagesList = this.state.images.map((image, i) => {
                return (<div key={i} className="box" >
                    <div className="label">{image.name}</div>
                    {/*This is where the bind/curry should be */}
                    <img onClick={this.loadOne.bind(this, image.url)} src={image.url} className="image" />
                </div>
                )
            });

            return (
                <div>
                    <button onClick={this.loadImages}>Click</button>
                    <div>{imagesList}</div>
                </div>
            );
        }
    }

ReactDOM.render(<App />, document.getElementById('container'));

然后将使用result.pano调用您的clickhandler(loadOne),并将该事件作为第二个参数通过react传入。

http://jsbin.com/zokugitopa/1/edit?js,output