在反应回调中使用bind两次传递给子

时间:2017-06-03 00:16:58

标签: javascript reactjs

我有一个类似的应用程序:

Main.js -

import React, { Component } from 'react';
import _ from 'underscore';

import { pick_attributes } from '../utils/general';
import ApplicationsButtons from '../components/ApplicationsButtons';
import BasicList from '../components/BasicList';


let API_BASE_URL = 'http://127.0.0.1:8889/api/'


export default class Main extends Component {

    constructor(props) {
      super(props);
      this.state = {
          new_role: '',
          new_task: '',
          applications: [],
          selected_app_id: 1,
          roles: [],
          tasks: []
      };
      this.updateSelectedApp = this.updateSelectedApp.bind(this);
      this.updateApplicationData = this.updateApplicationData.bind(this);
      this.loadAppData = this.loadAppData.bind(this);
      this.getSelectedApplicationData = this.getSelectedApplicationData.bind(this);
      this.setApplicationData = this.setApplicationData.bind(this);

      this.handleItemFormChange = this.handleItemFormChange.bind(this);
      this.submitAddItemForm = this.submitAddItemForm.bind(this);

      this.addItemByAjax = this.addItemByAjax.bind(this);
      this.deleteItemByAjax = this.deleteItemByAjax.bind(this);
    }

...

剩下的Main.js -

deleteItemByAjax(item_type, item_id) {
          let self = this;
          let url = API_BASE_URL + item_type + '/' + item_id;
            $.ajax({
                url: url,
                method: 'DELETE',
                success: function(response) {
                    self.loadAppData();
                }
            })
        }

        render() {

            return (
              <div>
                <br/>
                <ApplicationsButtons
                  apps={this.state.applications}
                  clickHandler={this.updateSelectedApp}/>
                <BasicList
                    items={this.state.roles}
                    deleteCallback={this.deleteItemByAjax.bind(this, 'roles')}
                    item_type="roles"
                    title="Roles"/>
                <form onSubmit={this.submitAddItemForm.bind(this, 'roles', 'new_role')}>
                  <label>
                    Add new role:
                    <input type="text" value={this.state.new_role} onChange={this.handleItemFormChange.bind(this, 'new_role')} />
                  </label>
                  <input type="submit" value="Add role" />
                </form>

                <BasicList
                    items={this.state.tasks}
                    deleteCallback={this.deleteItemByAjax.bind(this, 'tasks')}
                    title="Tasks"/>

                <form onSubmit={this.submitAddItemForm.bind(this, 'tasks', 'new_task')}>
                  <label>
                    Add new task:
                    <input type="text" value={this.state.new_task} onChange={this.handleItemFormChange.bind(this, 'new_task')} />
                  </label>
                  <input type="submit" value="Add task" />
                </form>
              </div>
            );
        }
    }

BasicList.js -

import React, { Component } from 'react';
import Select from 'react-select';
// import 'react-select/dist/react-select.css';

var options = [
  { value: 'one', label: 'One' },
  { value: 'two', label: 'Two' }
];

export default class BasicList extends Component {

    constructor(props) {
        super(props);
        this.state = {};
        this.logChange = this.logChange.bind(this);
    }

    logChange(val) {
        console.log("Selected: " + val.value);
    }

    render() {
        var li_elements = null;
        let items = this.props.items;
        if (items.length > 0) {
          li_elements = items.map(function(role) {
              console.log(role);
              return (
                  <li key={role.id}>
                      {role.name} -
                      <button onClick={() => this.props.deleteCallback.bind(this, role.id)}>
                        Delete
                      </button>
                  </li>
              );
          });
        }

        return (
          <div>
            <h4>{this.props.title}:</h4>
                <ul>
                    {li_elements}
                </ul>

                {/*}
                <Select
                  styles={ {maxWidth: 100} }
                  name="form-field-name"
                  value=""
                  options={options}
                  onChange={this.logChange}
                /> */}
          </div>
        );
    }
}

我的目标是尽可能干净地使用这个deleteItemByAjax,在这种情况下,在传递给子节点之前绑定item_type控制器中的第一个参数Main。但是我收到了错误

bundle.js:23712 Uncaught TypeError: Cannot read property 'props' of undefined
    at onClick

当我单击这些角色/任务的Delete按钮时。

所以,我首先尝试传入

deleteCallback={this.deleteItemByAjax.bind(this, 'roles')}

然后像

一样使用它

<button onClick={() => this.props.deleteCallback.bind(this, role.id)}>

如何在item_type中绑定第一个参数Main,然后为id组件中的这些项绑定BasicList?谢谢

        <BasicList
            items={this.state.roles}
            deleteCallback={this.deleteItemByAjax}
            item_type="roles"
            title="Roles"/>

然后

<button onClick={() => {this.props.deleteCallback(this.props.item_type, role.id)} }>
      Delete
</button>

也会因同样的错误而失败

2 个答案:

答案 0 :(得分:1)

你应该绑定这个func,你只需要将它命名为this.props.deleteCallback(this.props.item_type,role.id)并删除所有绑定。

答案 1 :(得分:1)

由先生解决。 Heinser:

render() {
    let li_elements = null;
    let items = this.props.items;

    if (items.length > 0) {
      li_elements = items.map((role) => {
          console.log(role);
          return (
              <li key={role.id}>
                  {role.name} -
                  <button onClick={() => {this.props.deleteCallback(this.props.item_type, role.id)} }>
                    Delete
                  </button>
              </li>
          );
      });
    }