在ReactJS中通过来自父状态的道具传递函数

时间:2018-01-16 19:32:36

标签: reactjs

所以这可能有点令人困惑所以我会尽力简化它。

我的状态包含父组件App.js中的对象数组。这是一个对象的例子。

{
category: "sample category",
API: "API URL",
active: function()
}

在我的子组件Category.js中,我通过道具传递了该数组。子项呈现ul,然后映射数组以为每个类别创建li。每个列表项都应该有一个onClick事件,该事件触发对象中的关联active: function()

由于某种原因,这不起作用。如果我运行一个函数是简单console.log("success")的测试,那就没问题了。所以列表项是通过我的道具获取功能并运行它。

这让我相信这就是我正在运行的实际功能。我正在尝试运行的功能是这个(位于App.js

function() {
  this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
  this.setState({showQuestions: true});
}

正在设置的状态位于App.js,该函数也位于App.js中,但正由Category.js中的列表项通过道具运行。这是我的问题吗?我可以不通过子组件中的函数运行来调整App.js的状态吗?

编辑:这里有更多的代码可以帮助找出解决方案。

实际错误:未捕获的TypeError:无法读取未定义的属性'setState'     在catMovies(App.js:71)

App.js:71是this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});函数的catMovies()

我的App.js构造函数

constructor(props) {
super(props);
this.state = {
  showCategories: false,
  showQuestions: false,
  isQuestionLoaded: false,
  categories: [{
    category: "movies",
    API: "https://opentdb.com/api.php?amount=10&category=11",
    active: this.catMovies
  }, {
    category: "sports",
    API: "https://opentdb.com/api.php?amount=10&category=21",
    active: this.catSports
  }, {
    category: "books",
    API: "https://opentdb.com/api.php?amount=10&category=10",
    active: this.catBooks
  }, {
    category: "videogames",
    API: "https://opentdb.com/api.php?amount=10&category=15",
    active: this.catVideogames
  }, {
    category: "general",
    API: "https://opentdb.com/api.php?amount=10&category=9",
    active: this.catGeneral
  }, {
    category: "everything",
    API: "https://opentdb.com/api.php?amount=10",
    active: this.catEverything
  }],
  categoryActive: "",
  questionNumber: 0,
  questionTotal: null,
  correct: [],
  score: 0,
  showFinal: false,
  testState: "test"
};
this.showCategories = this.showCategories.bind(this);
this.showQuestions = this.showQuestions.bind(this);
this.catMovies = this.catMovies.bind(this);
}

以下是App.js中的实际功能:

catMovies() {
  this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
  this.setState({showQuestions: true});
}

以下是App.js的回复,称为儿童权益:

<Categories categoryList={ this.state.categories } onClick={ this.catMovies } />

最后,这是子组件中使用所有这些的映射:

const categoryListItems = this.props.categoryList.map(cat =>
  <a href="#questionsContainer" key={cat.category + "link"}>
    <li onClick={cat.active} key={cat.category}>
      {cat.category}
    </li>
  </a>
);

2 个答案:

答案 0 :(得分:3)

你的问题在于处理程序的绑定 而不是像在构造函数中那样覆盖处理程序,而应该直接在状态初始化中执行:

this.state = {
  showCategories: false,
  showQuestions: false,
  isQuestionLoaded: false,
  categories: [{
    category: "movies",
    API: "https://opentdb.com/api.php?amount=10&category=11",
    active: this.catMovies.bind(this) // <-- you need to bind here
  },
 //...

这是一个包含两种模式的运行示例,请注意turnOff处理程序将如何抛出相同的错误:

&#13;
&#13;
const LightBall = ({ on }) => {
  return (
    <div>{`The light is ${on ? 'On' : 'Off'}`}</div>
  );
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      lightOn: false,
      toggle: this.toggleLight.bind(this), // this will work
      turnOff: this.turnOff // this will not work
    };
    this.turnOff = this.turnOff.bind(this);
  }

  toggleLight(){this.setState({ lightOn: !this.state.lightOn })};

  turnOff() { this.setState({ lightOn: false }) };

  render() {
    const { lightOn, toggle, turnOff } = this.state;
    return (
      <div>
        <button onClick={toggle}>Toggle Light</button>
        <button onClick={turnOff}>Turn Off</button>
        <LightBall on={lightOn} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

问题可能是由于这个功能

function() {
  this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
  this.setState({showQuestions: true});
}

this被称为调用函数的类。

您可以通过使用App将数组传递给子项之前将函数绑定到bind()组件来解决此问题(请参阅此处https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

或者您可以使用箭头函数,如果您在App组件中定义它以自动将其范围绑定到该组件,那么

{
category: "sample category",
API: "API URL",
active: () => {
    this.setState({categoryActive: "https://opentdb.com/api.php?amount=20&category=11"});
    this.setState({showQuestions: true});
  }
}

在此处详细了解箭头功能https://babeljs.io/learn-es2015/#arrows-and-lexical-this