处理数组项上的事件将不起作用 - ReactJS

时间:2018-01-08 14:52:37

标签: javascript arrays reactjs event-handling

我尝试映射数组并将click事件放在数组项上。我知道它有点不同,因为JavaScript如何处理函数,但我不能使它工作。我收到错误:无法读取未定义的属性'saveInStorage'。谁能告诉我我做错了什么?提前致谢!这是我的代码:

import React from "react";

const data = require('../data.json');

export default class Gebruikers extends React.Component {

    constructor() {
        super();
        this.state = {
            users: data.users
        };
        this.saveInStorage = this.saveInStorage.bind(this)
    }

    saveInStorage(e){
        console.log("test");
    }

    renderUser(user, i) {
        return(
            <p key={i} onClick={this.saveInStorage(user)}>f</p>
        );  
    }

    render() {
        return (
            <div>
                {
                    this.state.users.map(this.renderUser)
                }
            </div>
        );
    }
}

5 个答案:

答案 0 :(得分:2)

this中未定义

renderUser() 您需要在构造函数中绑定this renderUser()。 此外,每次渲染组件时都会调用saveInStorage(),而不仅仅是onClick,因此您需要在renderUser中使用箭头函数

import React from "react";

const data = require('../data.json');

export default class Gebruikers extends React.Component {

  constructor() {
    super();
    this.state = {
        users: data.users
    };
    this.saveInStorage = this.saveInStorage.bind(this);
    this.renderUser = this.renderUser.bind(this);
  }

  saveInStorage(e){
    console.log("test");
  }

  renderUser(user, i) {
    return(
        <p key={i} onClick={() => this.saveInStorage(user)}>
    );  
  }

  render() {
    return (
        <div>
            {
                this.state.users.map(this.renderUser)
            }
        </div>
    );
  }
}

除了绑定,您还可以使用箭头功能(根据mersocarlin的回答)。箭头函数也可以工作的唯一原因是“箭头函数没有自己的这个;使用封闭执行上下文的这个值”(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)。在您的情况下,封闭执行是您的渲染,其中定义了this

答案 1 :(得分:1)

您的onClick事件处理程序错误。 只需将其更改为:

onClick={() => this.saveInStorage(user)}

不要忘记在构造函数中绑定renderUser。 或者,您可以选择箭头函数方法,因为它们的工作方式与bind相同:

class Gebruikers extends React.Component {
  constructor(props) {
    super(props)
    
    this.state = {
      users: [{ id: 1, name: 'user1' }, { id: 2, name: 'user2' }],
    }
  }

  saveInStorage = (e) => {
    alert("test")
  }

  renderUser = (user, i) => {
    return(
      <p key={i} onClick={() => this.saveInStorage(user)}>
        {user.name}
      </p>
    )  
  }

  render() {
    return (
      <div>{this.state.users.map(this.renderUser)}</div>
    );
  }
}

ReactDOM.render(
  <Gebruikers />,
  document.getElementById('root')
)
<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="root"></div>

答案 2 :(得分:1)

您需要对代码进行两处更改,如下所示。

  1. 在呈现组件时调用该函数。要修复此更新,请将此行更新为以下

    <p key={i} onClick={() => this.saveInStorage(user)}>
    
  2. 这意味着只有在单击项目时才会调用该函数。

    1. 您还需要在构造函数中绑定renderUser,否则请使用箭头函数。

      this.renderUser = this.renderUser.bind(this);
      
    2. 参见工作示例here

答案 3 :(得分:1)

Paul Fitzgeralds的回答是正确的,尽管我想提出一种不同的处理方法,但没有所有约束性问题。

import React from "react";

const data = require('../data.json');

export default class Gebruikers extends React.Component {

    constructor() {
        super();
        this.state = {
            users: data.users
        };
    }

    saveInStorage = (e) => {
        console.log("test");
    };

    render() {
        return (
            <div>
                {this.state.users.map((user, i) => {
                    return (<p key={i} onClick={() => this.saveInStorage(user)}>f</p>);
                })}
            </div>
        );
    }
}

使用saveInStorage = (e) => {};,您将saveInStorage函数绑定到类的this上下文。在调用saveInStorage时,您将始终拥有(至少在这种情况下我猜是这样)期望的this上下文。

renderUser函数基本上是多余的。如果返回一行JSX,则可以在渲染函数中轻松完成。我认为它提高了可读性,因为你的所有JSX都在一个函数中。

答案 4 :(得分:0)

您没有将参数发送到this.renderUser

this.state.users.map((user, i) => this.renderUser(user, i))

此外,您的onClick功能应略有改变。这是完整的代码更改:

import React from "react";

const data = require('../data.json');

export default class Gebruikers extends React.Component {

    constructor() {
        super();
        this.state = {
            users: data.users
        };
        this.saveInStorage = this.saveInStorage.bind(this)
    }

    saveInStorage(e){
        console.log("test");
    }

    renderUser(user, i) {
        return(
            <p key={i} onClick={() => this.saveInStorage(user)}>f</p>
        );  
    }

    render() {
        return (
            <div>
                {
                    this.state.users.map((user, i) => this.renderUser(user, i))
                }
            </div>
        );
    }
}