React从其他组件调用函数

时间:2019-06-04 10:06:38

标签: javascript reactjs

我是ReactJS的新手,我正在用ReactJS做一个简单的CRUD。

我想在HeroModel类的Heroes列表中添加一个新Hero。但是我不知道如何从AddHero.js中调用HeroModel.js中的AddHero函数。

这是我的代码:

HeroModel.js

import React, { Component } from 'react';

class HeroModel {

state = {
    Heroes: [
        { Id: 1, Name: "hero1", Dob: new Date("1-1-2017"), Stocked: true, Price: 1.50 },
        { Id: 2, Name: "hero2", Dob: new Date("5-31-2018"), Stocked: false, Price: 2.50 },
        { Id: 3, Name: "hero3", Dob: new Date("2019"), Stocked: true, Price: 3.50 },
        { Id: 4, Name: "hero4", Dob: new Date("4-20-2010"), Stocked: false, Price: 4.50 },
        { Id: 5, Name: "hero5", Dob: new Date("12-31-2018"), Stocked: true, Price: 5.50 },
    ]
}

GetAllHeroes() {
    return this.state.Heroes;
}

AddHero(name, dob, stocked, price) {
    let id = this.state.Heroes.length + 1;
    this.state.Heroes = [...this.state.Heroes,
    { Id: id, Name: name, Dob: dob, Stocked: stocked, Price: price }];
    }
}

export default HeroModel;

AddHero.js

import React, { Component } from 'react';
import HeroModel from './HeroModel';

class AddHero extends Component {

constructor(props) {
    super(props);

    this.state = {
        Id: 0, Name: "", Dob: new Date(), Stocked: true, Price: 0
    };

}

onNameChange(e) {
    this.setState({
        Name: e.target.value
    });
}

onDobChange(e) {
    this.setState({
        Dob: e.target.value
    });
}

onStockedChange(e) {
    this.setState({
        Stocked : e.target.value
    });
}

onPriceChange(e) {
    this.setState({
        Price : e.target.value
    });
}

onSave(e){
//----I get stuck here-----
//    (new HeroModel).AddHero(
//        this.state.Name, this.state.Dob, 
//        this.state.Stocked, this.state.Price);
}

render() {
    return (
        <div>
            <h1>Add hero</h1>
            <form>
                <div className="form-group">
                    <label>Name </label>
                    <input type="text" onChange={this.onNameChange.bind(this)}></input>
                </div>
                <div className="form-group">
                    <label>Dob </label>
                    <input type="date" onChange={this.onDobChange.bind(this)} defaultValue={new Date().toISOString().substr(0, 10)}></input>
                </div>
                <div className="form-group">
                    <label>Stocked </label>
                    <input type="checkbox" onChange={this.onStockedChange.bind(this)} ></input>
                </div>
                <div className="form-group">
                    <label>Price </label>
                    <input type="text" onChange={this.onPriceChange.bind(this)}></input>
                </div>
                <button onClick={this.onSave.bind(this)}>Save</button>
            </form>
        </div>
    );
}
}

export default AddHero;

请帮助我在HeroMode.js中的英雄列表中添加新英雄。 我在函数onSave(e)处卡住了。

谢谢你。

1 个答案:

答案 0 :(得分:1)

编辑,有关Redux的实现,请参见以下沙箱:https://codesandbox.io/s/simple-reactredux-flow-l9oq4

要调用在另一个函数中定义的函数,您需要将其作为属性传递。这将创建一个父子关系。

让我们考虑以下问题:

  1. 您的父级组件将Heroes的列表保持在其状态。
  2. 您的父级组件具有一项功能,可让您添加更多英雄。 我们将其称为createNewHero()
  3. 您的父级组件将createNewHero()向下传递给 孩子AddHero
  4. AddHero将输入数据保存在其state中,我们会将这些数据作为对象传递给道具createNewHero()。有效地向上传递数据。
  5. 调用createNewHero()时,其执行上下文将绑定到 父组件。因此,当执行this.setState()时,关键字this指向HeroModel's状态。
  6. 完成后,我们将一个Hero添加到列表中,从而更改 状态,导致我们的组件重新渲染。

检出以下沙箱以查看实际效果:https://codesandbox.io/s/frosty-dawn-l9oq4

HeroModel(父级)

import React from "react";
import ReactDOM from "react-dom";
import AddHero from "./AddHero";

import "./styles.css";

class HeroModel extends React.Component {
  state = {
    Heroes: [
      {
        Id: 1,
        Name: "hero1",
        Dob: new Date("1-1-2017"),
        Stocked: true,
        Price: 1.5
      },
      {
        Id: 2,
        Name: "hero2",
        Dob: new Date("5-31-2018"),
        Stocked: false,
        Price: 2.5
      },
      {
        Id: 3,
        Name: "hero3",
        Dob: new Date("2019"),
        Stocked: true,
        Price: 3.5
      },
      {
        Id: 4,
        Name: "hero4",
        Dob: new Date("4-20-2010"),
        Stocked: false,
        Price: 4.5
      },
      {
        Id: 5,
        Name: "hero5",
        Dob: new Date("12-31-2018"),
        Stocked: true,
        Price: 5.5
      }
    ]
  };

  createNewHero = newHero => {
    this.setState({
      ...this.state,
      Heroes: [...this.state.Heroes, newHero]
    });
  };

  renderHeros = () => {
    const { Heroes } = this.state;

    return Heroes.map(hero => {
      return <div>{hero.Name}</div>;
    });
  };

  render() {
    return (
      <div>
        {this.renderHeros()}
        <AddHero createNewHero={this.createNewHero} />
      </div>
    );
  }
}
export default HeroModel;

AddHero(儿童)

import React from "react";

class AddHero extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      Id: 0,
      Name: "",
      Dob: new Date(),
      Stocked: true,
      Price: 0
    };
  }

  onSave = e => {
    e.preventDefault();
    const { Id, Name, Stocked, Price } = this.state;
    const newHero = {
      Id: Id,
      Name: Name,
      Dob: new Date(),
      Stocked: Stocked,
      Price: Price
    };

    this.props.createNewHero(newHero);
  };

  onChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  render() {
    return (
      <div>
        <h1>Add hero</h1>
        <form>
          <div className="form-group">
            <label>Name </label>
            <input type="text" onChange={this.onChange} name="Name" />
          </div>
          <div className="form-group">
            <label>Dob </label>
            <input
              type="date"
              onChange={this.onChange}
              defaultValue={new Date().toISOString().substr(0, 10)}
              name="Dob"
            />
          </div>
          <div className="form-group">
            <label>Stocked </label>
            <input type="checkbox" onChange={this.onChange} name="Stocked" />
          </div>
          <div className="form-group">
            <label>Price </label>
            <input type="text" onChange={this.onChange} name="Price" />
          </div>
          <button onClick={this.onSave}>Save</button>
        </form>
      </div>
    );
  }
}

export default AddHero;